First perfect square in base n with n unique digits: Difference between revisions

m
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
 
(45 intermediate revisions by 22 users not shown)
Line 24:
;* [[Casting out nines]]
<br>
 
=={{header|11l}}==
{{trans|Nim}}
 
<syntaxhighlight lang="11l">L(base) 2..16
V n = Int64(Float(base) ^ ((base - 1) / 2))
L
V sq = n * n
V sqstr = String(sq, radix' base)
I sqstr.len >= base & Set(Array(sqstr)).len == base
V nstr = String(n, radix' base)
print(‘Base #2: #8^2 = #.’.format(base, nstr, sqstr))
L.break
n++</syntaxhighlight>
 
{{out}}
<pre>
Base 2: 10^2 = 100
Base 3: 22^2 = 2101
Base 4: 33^2 = 3201
Base 5: 243^2 = 132304
Base 6: 523^2 = 452013
Base 7: 1431^2 = 2450361
Base 8: 3344^2 = 13675420
Base 9: 11642^2 = 136802574
Base 10: 32043^2 = 1026753849
Base 11: 111453^2 = 1240A536789
Base 12: 3966B9^2 = 124A7B538609
Base 13: 3828943^2 = 10254773CA86B9
Base 14: 3A9DB7C^2 = 10269B8C57D3A4
Base 15: 1012B857^2 = 102597BACE836D4
Base 16: 404A9D9B^2 = 1025648CFEA37BD9
</pre>
 
=={{header|ALGOL 68}}==
Assumes LONG INT is at least 64 bits as in e.g., Algol 68G
<syntaxhighlight lang="algol68">
BEGIN # find the first perfect square in base n with n unique digits n=1..16 #
[ 0 : 15 ]BITS dmask; # masks for recording the digits in a BITS string #
dmask[ 0 ] := 16r1;
FOR i TO UPB dmask DO dmask[ i ] := BIN ( 2 * ABS dmask[ i - 1 ] ) OD;
# base digits #
STRING digits = "0123456789abcdefghijklmnopqrstuvwxyz";
# returns a string representation of n in base b #
# the result is balank padded on the left to at least w digits #
PROC to base = ( LONG INT n, INT b, w )STRING:
BEGIN
STRING result := "";
LONG INT v := ABS n;
WHILE v > 0 DO
digits[ SHORTEN ( v MOD b ) + 1 ] +=: result;
v OVERAB b
OD;
IF INT len = ( UPB result - LWB result ) + 1;
len < w
THEN
( ( w - len ) * " " ) + result
ELSE result
FI
END # to base # ;
BITS all digits := dmask[ 0 ];
FOR b FROM 2 TO 16 DO
all digits := all digits OR dmask[ b - 1 ];
LONG INT root := 1;
FOR i TO b - 1 DO
root *:= b
OD;
root := ENTIER long sqrt( root );
BOOL found := FALSE;
WHILE NOT found DO
LONG INT square = root * root;
LONG INT v := square;
BITS present := 16r0;
WHILE v > 0 DO
present := present OR dmask[ SHORTEN ( v MOD b ) ];
v OVERAB b
OD;
IF found := present = all digits THEN
print( ( "Base: ", whole( b, -2 )
, ":", to base( root, b, 20 ), "^2 = ", to base( square, b, 0 )
, newline
)
)
FI;
root +:= 1
OD
OD
END
</syntaxhighlight>
{{out}}
<pre>
Base: 2: 10^2 = 100
Base: 3: 22^2 = 2101
Base: 4: 33^2 = 3201
Base: 5: 243^2 = 132304
Base: 6: 523^2 = 452013
Base: 7: 1431^2 = 2450361
Base: 8: 3344^2 = 13675420
Base: 9: 11642^2 = 136802574
Base: 10: 32043^2 = 1026753849
Base: 11: 111453^2 = 1240a536789
Base: 12: 3966b9^2 = 124a7b538609
Base: 13: 3828943^2 = 10254773ca86b9
Base: 14: 3a9db7c^2 = 10269b8c57d3a4
Base: 15: 1012b857^2 = 102597bace836d4
Base: 16: 404a9d9b^2 = 1025648cfea37bd9
</pre>
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
 
Line 60 ⟶ 167:
 
for (pos = 0; buffer[pos] != 0; pos++) {
if (buffer[pos] >!= ' '1) {
count++;
for (nxt = pos + 1; buffer[nxt] != 0; nxt++) {
}
for (nxt = pos + 1; if (buffer[nxt] !== 0; nxt++buffer[pos]) {
if (buffer[nxt] > ' ' && buffer[pos] == buffer[nxt]) {= 1;
buffer[nxt] = 1;}
}
}
Line 99 ⟶ 206:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>Base 2 : Num 10 Square 100
Line 116 ⟶ 223:
Base 15 : Num 1012B857 Square 102597BACE836D4</pre>
 
=={{header|C# sharp|CsharpC#}}==
{{libheader|System.Numerics}}
{{trans|Visual Basic .NET}}
Based on the Visual Basic .NET version, plus it shortcuts some of the ''allIn()'' checks. When the numbers checked are below a threshold, not every digit needs to be checked, saving a little time.
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Numerics;
Line 241 ⟶ 348:
Console.WriteLine("Elasped time was {0,8:0.00} minutes", (DateTime.Now - st0).TotalMinutes);
}
}</langsyntaxhighlight>
{{out}}
<pre>base inc id root square test count time total
Line 277 ⟶ 384:
{{trans|C#}}
A stripped down version of the C#, using unsigned longs instead of BigIntegers, and shifted bits instead of a HashSet accumulator.
<langsyntaxhighlight Cpplang="cpp">#include <string>
#include <iostream>
#include <cstdlib>
Line 350 ⟶ 457:
cout << "\nComputation time was " << et.count() * 1000 << " milliseconds" << endl;
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>base inc id root sqr test count
Line 373 ⟶ 480:
=={{header|D}}==
{{trans|C}}
<langsyntaxhighlight lang="d">import std.algorithm;
import std.exception;
import std.math;
Line 426 ⟶ 533:
find(i);
}
}</langsyntaxhighlight>
{{out}}
<pre>Base 2 : Num 10 Square 100
Line 443 ⟶ 550:
Base 15 : Num 1012B857 Square 102597BACE836D4
Base 16 : Num 404A9D9B Square 1025648CFEA37BD9</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
 
 
<syntaxhighlight lang="Delphi">
 
 
 
function GetRadixString(L: int64; Radix: Byte): string;
{Converts integer a string of any radix}
const RadixChars: array[0..35] Of char =
('0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'G','H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z');
var I: integer;
var S: string;
var Sign: string[1];
begin
Result:='';
If (L < 0) then
begin
Sign:='-';
L:=Abs(L);
end
else Sign:='';
S:='';
repeat
begin
I:=L mod Radix;
S:=RadixChars[I] + S;
L:=L div Radix;
end
until L = 0;
Result:=Sign + S;
end;
 
 
function HasUniqueDigits(N: int64; Base: integer): boolean;
{Keep track of unique digits with bits in a mask}
var Mask,Bit: cardinal;
var I,Cnt: integer;
begin
Cnt:=0; Mask:=0;
repeat
begin
I:=N mod Base;
Bit:=1 shl I;
if (Bit and Mask)=0 then
begin
Mask:=Mask or Bit;
Inc(Cnt);
end;
N:=N div Base;
end
until N = 0;
Result:=Cnt=Base;
end;
 
 
function GetStartValue(Base: integer): Int64;
{Start with the first N-Digit number in the base}
var I: integer;
begin
Result:=1;
for I:=1 to Base-1 do Result:=Result*Base;
Result:=Trunc(Sqrt(Result+0.0))-1;
end;
 
 
function FindFirstSquare(Base: integer): int64;
{Test squares to find the first one with unique digits}
var Start: int64;
begin
Result:=GetStartValue(Base);
while Result<=high(integer) do
begin
if HasUniqueDigits(Result*Result,Base) then break;
Inc(Result);
end;
end;
 
 
procedure ShowFirstSquares(Memo: TMemo);
{Find and display first perfect square that uses all digits in bases 2-16}
var I: integer;
var N: int64;
var S1,S2: string;
begin
for I:=2 to 16 do
begin
N:=FindFirstSquare(I);
S1:=GetRadixString(N,I);
S2:=GetRadixString(N*N,I);
Memo.Lines.Add(Format('Base=%2d %14s^2 = %16s',[I,S1,S2]));
end;
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
Base= 2 10^2 = 100
Base= 3 22^2 = 2101
Base= 4 33^2 = 3201
Base= 5 243^2 = 132304
Base= 6 523^2 = 452013
Base= 7 1431^2 = 2450361
Base= 8 3344^2 = 13675420
Base= 9 11642^2 = 136802574
Base=10 32043^2 = 1026753849
Base=11 111453^2 = 1240A536789
Base=12 3966B9^2 = 124A7B538609
Base=13 3828943^2 = 10254773CA86B9
Base=14 3A9DB7C^2 = 10269B8C57D3A4
Base=15 1012B857^2 = 102597BACE836D4
Base=16 404A9D9B^2 = 1025648CFEA37BD9
Run Time = 28.2 sec
</pre>
 
 
=={{header|EasyLang}}==
{{trans|Nim}}
<syntaxhighlight>
alpha$ = "0123456789AB"
func$ itoa n b .
if n > 0
return itoa (n div b) b & substr alpha$ (n mod b + 1) 1
.
.
func unique s$ .
len dig[] 12
for c$ in strchars s$
ind = strpos alpha$ c$
dig[ind] = 1
.
for v in dig[]
cnt += v
.
return cnt
.
proc find b . .
n = floor pow b ((b - 1) div 2)
repeat
sq = n * n
sq$ = itoa sq b
until len sq$ >= b and unique sq$ = b
n += 1
.
n$ = itoa n b
print "Base " & b & ": " & n$ & "² = " & sq$
.
for base = 2 to 12
find base
.
</syntaxhighlight>
{{out}}
<pre>
Base 2: 10² = 100
Base 3: 22² = 2101
Base 4: 33² = 3201
Base 5: 243² = 132304
Base 6: 523² = 452013
Base 7: 1431² = 2450361
Base 8: 3344² = 13675420
Base 9: 11642² = 136802574
Base 10: 32043² = 1026753849
Base 11: 111453² = 1240A536789
Base 12: 3966B9² = 124A7B538609
</pre>
 
=={{header|F_Sharp|F#}}==
===The Task===
<langsyntaxhighlight lang="fsharp">
// Nigel Galloway: May 21st., 2019
let fN g=let g=int64(sqrt(float(pown g (int(g-1L)))))+1L in (Seq.unfold(fun(n,g)->Some(n,(n+g,g+2L))))(g*g,g*2L+1L)
Line 453 ⟶ 733:
let toS n g=let a=Array.concat [[|'0'..'9'|];[|'a'..'f'|]] in System.String(Array.rev(fG n g)|>Array.map(fun n->a.[(int n)]))
[2L..16L]|>List.iter(fun n->let g=fL n in printfn "Base %d: %s² -> %s" n (toS (int64(sqrt(float g))) n) (toS g n))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 474 ⟶ 754:
===Using [[Factorial base numbers indexing permutations of a collection]]===
On the discussion page for [[Factorial base numbers indexing permutations of a collection]] an anonymous contributor queries the value of [[Factorial base numbers indexing permutations of a collection]]. Well let's see him use an inverse Knuth shuffle to partially solve this task. This solution only applies to bases that do not require an extra digit. Still I think it's short and interesting.<br>Note that the minimal candidate is 1.0....0 as a factorial base number.
<langsyntaxhighlight lang="fsharp">
// Nigel Galloway: May 30th., 2019
let fN n g=let g=n|>Array.rev|>Array.mapi(fun i n->(int64 n)*(pown g i))|>Array.sum
Line 481 ⟶ 761:
printfn "%A" (fG 12|>Seq.head) // -> [|1; 2; 4; 10; 7; 11; 5; 3; 8; 6; 0; 9|]
printfn "%A" (fG 14|>Seq.head) // -> [|1; 0; 2; 6; 9; 11; 8; 12; 5; 7; 13; 3; 10; 4|]
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
The only thing this program does to save time is start the search at a root high enough such that its square has enough digits to be pandigital.
<langsyntaxhighlight lang="factor">USING: assocs formatting fry kernel math math.functions
math.parser math.ranges math.statistics sequences ;
IN: rosetta-code.A260182
Line 506 ⟶ 786:
: main ( -- ) 2 16 [a,b] [ show-base ] each ;
 
MAIN: main</langsyntaxhighlight>
{{out}}
<pre>
Line 525 ⟶ 805:
Base 16: 404a9d9b squared = 1025648cfea37bd9
</pre>
 
=={{header|Forth}}==
<syntaxhighlight lang="forth">
#! /usr/bin/gforth-fast
 
: 2^ 1 swap lshift ;
 
: sq s" dup *" evaluate ; immediate
 
: min-root ( -- n ) \ minimum root that can be pandigitial
base @ s>f fdup 1e f- 0.5e f* f** f>s ;
 
: pandigital? ( n -- f )
0 swap \ bitmask
begin
base @ /mod
>r 2^ or r>
dup 0= until drop
base @ 2^ 1- = ;
 
: panroot ( -- n ) \ get the minimum square root using the variable BASE.
min-root 1- begin
1+
dup sq pandigital? until ;
 
: .squares ( -- )
base @ 17 2 do
i base !
i 2 dec.r 3 spaces panroot dup 8 .r ." ² = " sq . cr
loop base ! ;
 
.squares
bye
</syntaxhighlight>
{{Out}}
<pre>
2 10² = 100
3 22² = 2101
4 33² = 3201
5 243² = 132304
6 523² = 452013
7 1431² = 2450361
8 3344² = 13675420
9 11642² = 136802574
10 32043² = 1026753849
11 111453² = 1240A536789
12 3966B9² = 124A7B538609
13 3828943² = 10254773CA86B9
14 3A9DB7C² = 10269B8C57D3A4
15 1012B857² = 102597BACE836D4
16 404A9D9B² = 1025648CFEA37BD9
</pre>
 
=={{header|FreeBASIC}}==
{{trans|XPLo}}
<syntaxhighlight lang="vbnet">#define floor(x) ((x*2.0-0.5) Shr 1)
 
Dim Shared As Double n, base_ = 2. ' Base is a reserved word on FB
 
Sub NumOut(n As Double) 'Display n in the specified base
Dim As Integer remainder = Fix(n Mod base_)
n = floor(n / base_)
If n <> 0. Then NumOut(n)
Print Chr(remainder + Iif(remainder <= 9, Asc("0"), Asc("A")-10));
End Sub
 
Function isPandigital(n As Double) As Boolean
Dim As Integer used, remainder
used = 0
While n <> 0.
remainder = Fix(n Mod base_)
n = floor(n / base_)
used Or= 1 Shl remainder
Wend
Return used = (1 Shl Fix(base_)) - 1
End Function
 
Do
n = floor(Sqr(base_ ^ (base_-1.)))
Do
If isPandigital(n*n) Then
Print Using "Base ##: "; base_;
NumOut(n)
Print "^2 = ";
NumOut(n*n)
Print
Exit Do
End If
n += 1.
Loop
base_ += 1.
Loop Until base_ > 14.
 
Sleep</syntaxhighlight>
{{out}}
<pre>Base 2: 10^2 = 100
Base 3: 22^2 = 2101
Base 4: 33^2 = 3201
Base 5: 243^2 = 132304
Base 6: 523^2 = 452013
Base 7: 1431^2 = 2450361
Base 8: 3344^2 = 13675420
Base 9: 11642^2 = 136802574
Base 10: 32043^2 = 1026753849
Base 11: 111453^2 = 1240A536789
Base 12: 3966B9^2 = 124A7B538609
Base 13: 3828943^2 = 10254773CA86B9
Base 14: 3A9DB7C^2 = 10269B8C57D3A4</pre>
 
=={{header|Go}}==
This takes advantage of major optimizations described by Nigel Galloway and Thundergnat (inspired by initial pattern analysis by Hout) in the Discussion page and a minor optimization contributed by myself.
<langsyntaxhighlight lang="go">package main
 
import (
Line 668 ⟶ 1,056:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 704 ⟶ 1,092:
 
For example, to reach base 28 (the largest base shown in the OEIS table) we have:
<langsyntaxhighlight lang="go">package main
 
import (
Line 760 ⟶ 1,148:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 792 ⟶ 1,180:
Base 28: 58a3ckp3n4cqd7² = 1023456cgjbirqedhp98kmoan7fl in 911.059s
</pre>
 
=={{header|Haskell}}==
{{trans|F#}}
<syntaxhighlight lang="haskell">import Control.Monad (guard)
import Data.List (find, unfoldr)
import Data.Char (intToDigit)
import qualified Data.Set as Set
import Text.Printf (printf)
digits :: Integral a => a -> a -> [a]
digits
b = unfoldr
(((>>) . guard . (0 /=)) <*> (pure . ((,) <$> (`mod` b) <*> (`div` b))))
sequenceForBaseN :: Integral a => a -> [a]
sequenceForBaseN
b = unfoldr (\(v, n) -> Just (v, (v + n, n + 2))) (i ^ 2, i * 2 + 1)
where
i = succ (round $ sqrt (realToFrac (b ^ pred b)))
searchSequence :: Integral a => a -> Maybe a
searchSequence
b = find ((digitsSet ==) . Set.fromList . digits b) (sequenceForBaseN b)
where
digitsSet = Set.fromList [0 .. pred b]
display :: Integer -> Integer -> String
display b n = map (intToDigit . fromIntegral) $ reverse $ digits b n
main :: IO ()
main = mapM_
(\b -> case searchSequence b of
Just n -> printf
"Base %2d: %8s² -> %16s\n"
b
(display b (squareRootValue n))
(display b n)
Nothing -> pure ())
[2 .. 16]
where
squareRootValue = round . sqrt . realToFrac</syntaxhighlight>
{{out}}
<pre>Base 2: 10² -> 100
Base 3: 22² -> 2101
Base 4: 33² -> 3201
Base 5: 243² -> 132304
Base 6: 523² -> 452013
Base 7: 1431² -> 2450361
Base 8: 3344² -> 13675420
Base 9: 11642² -> 136802574
Base 10: 32043² -> 1026753849
Base 11: 111453² -> 1240a536789
Base 12: 3966b9² -> 124a7b538609
Base 13: 3828943² -> 10254773ca86b9
Base 14: 3a9db7c² -> 10269b8c57d3a4
Base 15: 1012b857² -> 102597bace836d4
Base 16: 404a9d9b² -> 1025648cfea37bd9</pre>
 
=={{header|J}}==
<syntaxhighlight lang="text">
pandigital=: [ = [: # [: ~. #.inv NB. BASE pandigital Y
</syntaxhighlight>
</lang>
<pre>
assert 10 pandigital 1234567890
Line 841 ⟶ 1,286:
+----+------------+------------+
</pre>
 
=={{header|Java}}==
{{trans|C#}}
<syntaxhighlight lang="java">import java.math.BigInteger;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
public class Program {
static final String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz|";
static byte base, bmo, blim, ic;
static long st0;
static BigInteger bllim, threshold;
static Set<Byte> hs = new HashSet<>();
static Set<Byte> o = new HashSet<>();
static final char[] chars = ALPHABET.toCharArray();
static List<BigInteger> limits;
static String ms;
 
static int indexOf(char c) {
for (int i = 0; i < chars.length; ++i) {
if (chars[i] == c) {
return i;
}
}
return -1;
}
 
// convert BigInteger to string using current base
static String toStr(BigInteger b) {
BigInteger bigBase = BigInteger.valueOf(base);
StringBuilder res = new StringBuilder();
while (b.compareTo(BigInteger.ZERO) > 0) {
BigInteger[] divRem = b.divideAndRemainder(bigBase);
res.append(chars[divRem[1].intValue()]);
b = divRem[0];
}
return res.toString();
}
 
// check for a portion of digits, bailing if uneven
static boolean allInQS(BigInteger b) {
BigInteger bigBase = BigInteger.valueOf(base);
int c = ic;
hs.clear();
hs.addAll(o);
while (b.compareTo(bllim) > 0) {
BigInteger[] divRem = b.divideAndRemainder(bigBase);
hs.add(divRem[1].byteValue());
c++;
 
if (c > hs.size()) {
return false;
}
b = divRem[0];
}
return true;
}
 
// check for a portion of digits, all the way to the end
static boolean allInS(BigInteger b) {
BigInteger bigBase = BigInteger.valueOf(base);
hs.clear();
hs.addAll(o);
while (b.compareTo(bllim) > 0) {
BigInteger[] divRem = b.divideAndRemainder(bigBase);
hs.add(divRem[1].byteValue());
b = divRem[0];
}
return hs.size() == base;
}
 
// check for all digits, bailing if uneven
static boolean allInQ(BigInteger b) {
BigInteger bigBase = BigInteger.valueOf(base);
int c = 0;
hs.clear();
while (b.compareTo(BigInteger.ZERO) > 0) {
BigInteger[] divRem = b.divideAndRemainder(bigBase);
hs.add(divRem[1].byteValue());
c++;
if (c > hs.size()) {
return false;
}
b = divRem[0];
}
return true;
}
 
// check for all digits, all the way to the end
static boolean allIn(BigInteger b) {
BigInteger bigBase = BigInteger.valueOf(base);
hs.clear();
while (b.compareTo(BigInteger.ZERO) > 0) {
BigInteger[] divRem = b.divideAndRemainder(bigBase);
hs.add(divRem[1].byteValue());
b = divRem[0];
}
return hs.size() == base;
}
 
// parse a string into a BigInteger, using current base
static BigInteger to10(String s) {
BigInteger bigBase = BigInteger.valueOf(base);
BigInteger res = BigInteger.ZERO;
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
int idx = indexOf(c);
BigInteger bigIdx = BigInteger.valueOf(idx);
res = res.multiply(bigBase).add(bigIdx);
}
return res;
}
 
// returns the minimum value string, optionally inserting extra digit
static String fixup(int n) {
String res = ALPHABET.substring(0, base);
if (n > 0) {
StringBuilder sb = new StringBuilder(res);
sb.insert(n, n);
res = sb.toString();
}
return "10" + res.substring(2);
}
 
// checks the square against the threshold, advances various limits when needed
static void check(BigInteger sq) {
if (sq.compareTo(threshold) > 0) {
o.remove((byte) indexOf(ms.charAt(blim)));
blim--;
ic--;
threshold = limits.get(bmo - blim - 1);
bllim = to10(ms.substring(0, blim + 1));
}
}
 
// performs all the calculations for the current base
static void doOne() {
limits = new ArrayList<>();
bmo = (byte) (base - 1);
byte dr = 0;
if ((base & 1) == 1) {
dr = (byte) (base >> 1);
}
o.clear();
blim = 0;
byte id = 0;
int inc = 1;
long st = System.nanoTime();
byte[] sdr = new byte[bmo];
byte rc = 0;
for (int i = 0; i < bmo; i++) {
sdr[i] = (byte) ((i * i) % bmo);
rc += sdr[i] == dr ? (byte) 1 : (byte) 0;
sdr[i] += sdr[i] == 0 ? bmo : (byte) 0;
}
long i = 0;
if (dr > 0) {
id = base;
for (i = 1; i <= dr; i++) {
if (sdr[(int) i] >= dr) {
if (id > sdr[(int) i]) {
id = sdr[(int) i];
}
}
}
id -= dr;
i = 0;
}
ms = fixup(id);
BigInteger sq = to10(ms);
BigInteger rt = BigInteger.valueOf((long) (Math.sqrt(sq.doubleValue()) + 1));
sq = rt.multiply(rt);
if (base > 9) {
for (int j = 1; j < base; j++) {
limits.add(to10(ms.substring(0, j) + String.valueOf(chars[bmo]).repeat(base - j + (rc > 0 ? 0 : 1))));
}
Collections.reverse(limits);
while (sq.compareTo(limits.get(0)) < 0) {
rt = rt.add(BigInteger.ONE);
sq = rt.multiply(rt);
}
}
BigInteger dn = rt.shiftLeft(1).add(BigInteger.ONE);
BigInteger d = BigInteger.ONE;
if (base > 3 && rc > 0) {
while (sq.remainder(BigInteger.valueOf(bmo)).compareTo(BigInteger.valueOf(dr)) != 0) {
rt = rt.add(BigInteger.ONE);
sq = sq.add(dn);
dn = dn.add(BigInteger.TWO);
} // aligns sq to dr
inc = bmo / rc;
if (inc > 1) {
dn = dn.add(rt.multiply(BigInteger.valueOf(inc - 2)).subtract(BigInteger.ONE));
d = BigInteger.valueOf(inc * inc);
}
dn = dn.add(dn).add(d);
}
d = d.shiftLeft(1);
if (base > 9) {
blim = 0;
while (sq.compareTo(limits.get(bmo - blim - 1)) < 0) {
blim++;
}
ic = (byte) (blim + 1);
threshold = limits.get(bmo - blim - 1);
if (blim > 0) {
for (byte j = 0; j <= blim; j++) {
o.add((byte) indexOf(ms.charAt(j)));
}
}
if (blim > 0) {
bllim = to10(ms.substring(0, blim + 1));
} else {
bllim = BigInteger.ZERO;
}
if (base > 5 && rc > 0)
while (!allInQS(sq)) {
sq = sq.add(dn);
dn = dn.add(d);
i += 1;
check(sq);
}
else {
while (!allInS(sq)) {
sq = sq.add(dn);
dn = dn.add(d);
i += 1;
check(sq);
}
}
} else {
if (base > 5 && rc > 0) {
while (!allInQ(sq)) {
sq = sq.add(dn);
dn = dn.add(d);
i += 1;
}
} else {
while (!allIn(sq)) {
sq = sq.add(dn);
dn = dn.add(d);
i += 1;
}
}
}
 
rt = rt.add(BigInteger.valueOf(i * inc));
long delta1 = System.nanoTime() - st;
Duration dur1 = Duration.ofNanos(delta1);
long delta2 = System.nanoTime() - st0;
Duration dur2 = Duration.ofNanos(delta2);
System.out.printf(
"%3d %2d %2s %20s -> %-40s %10d %9s %9s\n",
base, inc, (id > 0 ? ALPHABET.substring(id, id + 1) : " "), toStr(rt), toStr(sq), i, format(dur1), format(dur2)
);
}
 
private static String format(Duration d) {
int minP = d.toMinutesPart();
int secP = d.toSecondsPart();
int milP = d.toMillisPart();
return String.format("%02d:%02d.%03d", minP, secP, milP);
}
 
public static void main(String[] args) {
System.out.println("base inc id root square test count time total");
st0 = System.nanoTime();
for (base = 2; base < 28; ++base) {
doOne();
}
}
}</syntaxhighlight>
{{out}}
<pre>base inc id root square test count time total
2 1 01 -> 001 0 00:00.030 00:00.030
3 1 22 -> 1012 4 00:00.000 00:00.040
4 3 33 -> 1023 2 00:00.000 00:00.042
5 1 2 342 -> 403231 14 00:00.000 00:00.044
6 5 325 -> 310254 20 00:00.000 00:00.047
7 6 1341 -> 1630542 34 00:00.000 00:00.049
8 7 4433 -> 02457631 41 00:00.000 00:00.051
9 4 24611 -> 475208631 289 00:00.002 00:00.055
10 3 34023 -> 9483576201 17 00:00.023 00:00.080
11 10 354111 -> 987635A0421 1498 00:00.009 00:00.091
12 11 9B6693 -> 906835B7A421 6883 00:00.012 00:00.109
13 1 3 3498283 -> 9B68AC37745201 8242 00:00.053 00:00.164
14 13 C7BD9A3 -> 4A3D75C8B96201 1330 00:00.001 00:00.166
15 14 758B2101 -> 4D638ECAB795201 4216 00:00.008 00:00.175
16 15 B9D9A404 -> 9DB73AEFC8465201 18457 00:00.070 00:00.247
17 1 1 9AG28F324 -> DE753BFGC98A642101 195112 00:00.415 00:00.664
18 17 DAC284B44 -> 7HC9DA4GE8F5B63201 30440 00:00.015 00:00.680
19 6 A9E55B1101 -> 5E9A6F8IC7GBHD43201 93021 00:00.116 00:00.797
20 19 G3D5HIGD94 -> G8AJF596BH3IDC7E4201 11310604 00:06.544 00:07.342
21 1 6 F72EF5EH9C4 -> FAECK6B6J8IH9GD7543201 601843 00:01.123 00:08.467
22 21 F0JG88749F4 -> 5AKL7IHC84JEDGBF963201 27804949 00:16.134 00:24.602
23 22 CM65LE3D1101 -> 657LIJBF8MH9GKDECA43201 17710217 00:09.976 00:34.579
24 23 3DH0FGDH0JL4 -> 96ALDMGINJKCEFH78B543201 4266555 00:02.115 00:36.695
25 12 MHGHF541E1101 -> 9HN7MAIL8BFG6JKCEOD543201 78092124 00:47.584 01:24.280
26 5 K99MDB35N8K25 -> ABDJNHCPF97GKMEI6OL8543201 402922566 04:37.368 06:01.649
27 26 JJBO73E11F1101 -> A6N9QC7PKGFJIBHDMOLE8543201 457555291 05:19.215 11:20.866</pre>
 
=={{header|JavaScript}}==
{{Trans|Python}}
<langsyntaxhighlight lang="javascript">(() => {
'use strict';
 
Line 992 ⟶ 1,741:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>Smallest perfect squares using all digits in bases 2-12:
Line 1,008 ⟶ 1,757:
11 -> 111453 -> 1240a536789
12 -> 3966b9 -> 124a7b538609</pre>
 
=={{header|jq}}==
'''Adapted from [[#Julia|Julia]]'''
 
'''Works with jq and gojq, the C and Go implementations of jq'''
 
Some useful filters, but nothing fancy here.
 
With a few minor tweaks, notably replacing `sqrt` with `isqrt` (see e.g. [[Isqrt_(integer_square_root)_of_X#jq]]),
the following program also works with jaq, the Rust implementation of jq.
<syntaxhighlight lang=jq>
# Input: an integral decimal number
# Output: the representation of the input in base $b as
# an array of one-character digits, with the least significant digit first.
def tobaseDigits($b):
def digit: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[.:.+1];
def mod: . % $b;
def div: ((. - mod) / $b);
def digits: recurse( select(. > 0) | div) | mod ;
if . == 0 then "0"
else [digits | digit][:-1]
end;
 
def tobase($b):
tobaseDigits($b) | reverse | add;
 
# Input: an alphanumeric string to be interpreted as a number in base $b
# Output: the corresponding decimal value
def frombase($b):
def decimalValue:
if 48 <= . and . <= 57 then . - 48
elif 65 <= . and . <= 90 then . - 55 # (10+.-65)
elif 97 <= . and . <= 122 then . - 87 # (10+.-97)
else "decimalValue" | error
end;
reduce (explode|reverse[]|decimalValue) as $x ({p:1};
.value += (.p * $x)
| .p *= $b)
| .value ;
 
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
 
# $n and $base should be decimal integers
def hasallin($n; $base):
$base == ($n | tobaseDigits($base) | unique | length);
 
def squaresearch($base):
def num: "0123456789abcdef";
(("10" + num[2:$base]) | frombase($base)) as $highest
| first( range( $highest|sqrt|floor; infinite) # $highest + 1
| select(hasallin(.*.; $base)) );
 
def task:
"Base Root N",
(range(2;16) as $b
| squaresearch($b)
| "\($b|lpad(3)) \(tobase($b)|lpad(10) ) \( .*. | tobase($b))" );
 
task
</syntaxhighlight>
{{output}}
<pre>
Base Root N
2 10 100
3 22 2101
4 33 3201
5 243 132304
6 523 452013
7 1431 2450361
8 3344 13675420
9 11642 136802574
10 32043 1026753849
11 111453 1240A536789
12 3966B9 124A7B538609
13 3828943 10254773CA86B9
14 3A9DB7C 10269B8C57D3A4
15 1012B857 102597BACE836D4
</pre>
 
=={{header|Julia}}==
Runs in about 4 seconds with using occursin().
<langsyntaxhighlight lang="julia">const num = "0123456789abcdef"
hasallin(n, nums, b) = (s = string(n, base=b); all(x -> occursin(x, s), nums))
Line 1,029 ⟶ 1,856:
println(lpad(b, 3), lpad(string(n, base=b), 10), " ", string(n * n, base=b))
end
</langsyntaxhighlight>{{out}}
<pre>
Base Root N
Line 1,048 ⟶ 1,875:
16 404a9d9b 1025648cfea37bd9
</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">import java.math.BigInteger
import java.time.Duration
import java.util.ArrayList
import java.util.HashSet
import kotlin.math.sqrt
 
const val ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz|"
var base: Byte = 0
var bmo: Byte = 0
var blim: Byte = 0
var ic: Byte = 0
var st0: Long = 0
var bllim: BigInteger? = null
var threshold: BigInteger? = null
var hs: MutableSet<Byte> = HashSet()
var o: MutableSet<Byte> = HashSet()
val chars = ALPHABET.toCharArray()
var limits: MutableList<BigInteger?>? = null
var ms: String? = null
 
fun indexOf(c: Char): Int {
for (i in chars.indices) {
if (chars[i] == c) {
return i
}
}
return -1
}
 
// convert BigInteger to string using current base
fun toStr(b: BigInteger): String {
var b2 = b
val bigBase = BigInteger.valueOf(base.toLong())
val res = StringBuilder()
while (b2 > BigInteger.ZERO) {
val divRem = b2.divideAndRemainder(bigBase)
res.append(chars[divRem[1].toInt()])
b2 = divRem[0]
}
return res.toString()
}
 
// check for a portion of digits, bailing if uneven
fun allInQS(b: BigInteger): Boolean {
var b2 = b
val bigBase = BigInteger.valueOf(base.toLong())
var c = ic.toInt()
hs.clear()
hs.addAll(o)
while (b2 > bllim) {
val divRem = b2.divideAndRemainder(bigBase)
hs.add(divRem[1].toByte())
c++
if (c > hs.size) {
return false
}
b2 = divRem[0]
}
return true
}
 
// check for a portion of digits, all the way to the end
fun allInS(b: BigInteger): Boolean {
var b2 = b
val bigBase = BigInteger.valueOf(base.toLong())
hs.clear()
hs.addAll(o)
while (b2 > bllim) {
val divRem = b2.divideAndRemainder(bigBase)
hs.add(divRem[1].toByte())
b2 = divRem[0]
}
return hs.size == base.toInt()
}
 
// check for all digits, bailing if uneven
fun allInQ(b: BigInteger): Boolean {
var b2 = b
val bigBase = BigInteger.valueOf(base.toLong())
var c = 0
hs.clear()
while (b2 > BigInteger.ZERO) {
val divRem = b2.divideAndRemainder(bigBase)
hs.add(divRem[1].toByte())
c++
if (c > hs.size) {
return false
}
b2 = divRem[0]
}
return true
}
 
// check for all digits, all the way to the end
fun allIn(b: BigInteger): Boolean {
var b2 = b
val bigBase = BigInteger.valueOf(base.toLong())
hs.clear()
while (b2 > BigInteger.ZERO) {
val divRem = b2.divideAndRemainder(bigBase)
hs.add(divRem[1].toByte())
b2 = divRem[0]
}
return hs.size == base.toInt()
}
 
// parse a string into a BigInteger, using current base
fun to10(s: String?): BigInteger {
val bigBase = BigInteger.valueOf(base.toLong())
var res = BigInteger.ZERO
for (element in s!!) {
val idx = indexOf(element)
val bigIdx = BigInteger.valueOf(idx.toLong())
res = res.multiply(bigBase).add(bigIdx)
}
return res
}
 
// returns the minimum value string, optionally inserting extra digit
fun fixup(n: Int): String {
var res = ALPHABET.substring(0, base.toInt())
if (n > 0) {
val sb = StringBuilder(res)
sb.insert(n, n)
res = sb.toString()
}
return "10" + res.substring(2)
}
 
// checks the square against the threshold, advances various limits when needed
fun check(sq: BigInteger) {
if (sq > threshold) {
o.remove(indexOf(ms!![blim.toInt()]).toByte())
blim--
ic--
threshold = limits!![bmo - blim - 1]
bllim = to10(ms!!.substring(0, blim + 1))
}
}
 
// performs all the calculations for the current base
fun doOne() {
limits = ArrayList()
bmo = (base - 1).toByte()
var dr: Byte = 0
if ((base.toInt() and 1) == 1) {
dr = (base.toInt() shr 1).toByte()
}
o.clear()
blim = 0
var id: Byte = 0
var inc = 1
val st = System.nanoTime()
val sdr = ByteArray(bmo.toInt())
var rc: Byte = 0
for (i in 0 until bmo) {
sdr[i] = (i * i % bmo).toByte()
if (sdr[i] == dr) {
rc = (rc + 1).toByte()
}
if (sdr[i] == 0.toByte()) {
sdr[i] = (sdr[i] + bmo).toByte()
}
}
var i: Long = 0
if (dr > 0) {
id = base
i = 1
while (i <= dr) {
if (sdr[i.toInt()] >= dr) {
if (id > sdr[i.toInt()]) {
id = sdr[i.toInt()]
}
}
i++
}
id = (id - dr).toByte()
i = 0
}
ms = fixup(id.toInt())
var sq = to10(ms)
var rt = BigInteger.valueOf((sqrt(sq.toDouble()) + 1).toLong())
sq = rt.multiply(rt)
if (base > 9) {
for (j in 1 until base) {
limits!!.add(to10(ms!!.substring(0, j) + chars[bmo.toInt()].toString().repeat(base - j + if (rc > 0) 0 else 1)))
}
limits!!.reverse()
while (sq < limits!![0]) {
rt = rt.add(BigInteger.ONE)
sq = rt.multiply(rt)
}
}
var dn = rt.shiftLeft(1).add(BigInteger.ONE)
var d = BigInteger.ONE
if (base > 3 && rc > 0) {
while (sq.remainder(BigInteger.valueOf(bmo.toLong())).compareTo(BigInteger.valueOf(dr.toLong())) != 0) {
rt = rt.add(BigInteger.ONE)
sq = sq.add(dn)
dn = dn.add(BigInteger.TWO)
} // aligns sq to dr
inc = bmo / rc
if (inc > 1) {
dn = dn.add(rt.multiply(BigInteger.valueOf(inc - 2.toLong())).subtract(BigInteger.ONE))
d = BigInteger.valueOf(inc * inc.toLong())
}
dn = dn.add(dn).add(d)
}
d = d.shiftLeft(1)
if (base > 9) {
blim = 0
while (sq < limits!![bmo - blim - 1]) {
blim++
}
ic = (blim + 1).toByte()
threshold = limits!![bmo - blim - 1]
if (blim > 0) {
for (j in 0..blim) {
o.add(indexOf(ms!![j]).toByte())
}
}
bllim = if (blim > 0) {
to10(ms!!.substring(0, blim + 1))
} else {
BigInteger.ZERO
}
if (base > 5 && rc > 0) while (!allInQS(sq)) {
sq = sq.add(dn)
dn = dn.add(d)
i += 1
check(sq)
} else {
while (!allInS(sq)) {
sq = sq.add(dn)
dn = dn.add(d)
i += 1
check(sq)
}
}
} else {
if (base > 5 && rc > 0) {
while (!allInQ(sq)) {
sq = sq.add(dn)
dn = dn.add(d)
i += 1
}
} else {
while (!allIn(sq)) {
sq = sq.add(dn)
dn = dn.add(d)
i += 1
}
}
}
rt = rt.add(BigInteger.valueOf(i * inc))
val delta1 = System.nanoTime() - st
val dur1 = Duration.ofNanos(delta1)
val delta2 = System.nanoTime() - st0
val dur2 = Duration.ofNanos(delta2)
System.out.printf(
"%3d %2d %2s %20s -> %-40s %10d %9s %9s\n",
base, inc, if (id > 0) ALPHABET.substring(id.toInt(), id + 1) else " ", toStr(rt), toStr(sq), i, format(dur1), format(dur2)
)
}
 
private fun format(d: Duration): String {
val minP = d.toMinutesPart()
val secP = d.toSecondsPart()
val milP = d.toMillisPart()
return String.format("%02d:%02d.%03d", minP, secP, milP)
}
 
fun main() {
println("base inc id root square test count time total")
st0 = System.nanoTime()
base = 2
while (base < 28) {
doOne()
++base
}
}</syntaxhighlight>
{{out}}
<pre>base inc id root square test count time total
2 1 01 -> 001 0 00:00.001 00:00.002
3 1 22 -> 1012 4 00:00.000 00:00.016
4 3 33 -> 1023 2 00:00.000 00:00.018
5 1 2 342 -> 403231 14 00:00.000 00:00.021
6 5 325 -> 310254 20 00:00.000 00:00.023
7 6 1341 -> 1630542 34 00:00.000 00:00.026
8 7 4433 -> 02457631 41 00:00.000 00:00.028
9 4 24611 -> 475208631 289 00:00.002 00:00.032
10 3 34023 -> 9483576201 17 00:00.017 00:00.050
11 10 354111 -> 987635A0421 1498 00:00.011 00:00.063
12 11 9B6693 -> 906835B7A421 6883 00:00.016 00:00.083
13 1 3 3498283 -> 9B68AC37745201 8242 00:00.031 00:00.116
14 13 C7BD9A3 -> 4A3D75C8B96201 1330 00:00.002 00:00.120
15 14 758B2101 -> 4D638ECAB795201 4216 00:00.016 00:00.138
16 15 B9D9A404 -> 9DB73AEFC8465201 18457 00:00.087 00:00.226
17 1 1 9AG28F324 -> DE753BFGC98A642101 195112 00:00.435 00:00.664
18 17 DAC284B44 -> 7HC9DA4GE8F5B63201 30440 00:00.018 00:00.683
19 6 A9E55B1101 -> 5E9A6F8IC7GBHD43201 93021 00:00.061 00:00.745
20 19 G3D5HIGD94 -> G8AJF596BH3IDC7E4201 11310604 00:06.859 00:07.605
21 1 6 F72EF5EH9C4 -> FAECK6B6J8IH9GD7543201 601843 00:01.223 00:08.830
22 21 F0JG88749F4 -> 5AKL7IHC84JEDGBF963201 27804949 00:18.191 00:27.023
23 22 CM65LE3D1101 -> 657LIJBF8MH9GKDECA43201 17710217 00:11.143 00:38.167
24 23 3DH0FGDH0JL4 -> 96ALDMGINJKCEFH78B543201 4266555 00:02.381 00:40.549
25 12 MHGHF541E1101 -> 9HN7MAIL8BFG6JKCEOD543201 78092124 00:53.150 01:33.701
26 5 K99MDB35N8K25 -> ABDJNHCPF97GKMEI6OL8543201 402922566 05:15.307 06:49.008
27 26 JJBO73E11F1101 -> A6N9QC7PKGFJIBHDMOLE8543201 457555291 06:01.338 12:50.347</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[FirstSquare]
FirstSquare[b_Integer] := Module[{n, alldigits, digs, start},
digs = Range[0, b - 1];
digs[[{2, 1}]] //= Reverse;
start = Floor[Sqrt[FromDigits[digs, b]]];
n = start;
alldigits = Range[0, b - 1];
While[! ContainsAll[IntegerDigits[n^2, b], alldigits], n++];
{b, n, start, BaseForm[n, b]}
]
Scan[Print@*FirstSquare, Range[2, 16]]</syntaxhighlight>
{{out}}
<pre>{2,2,1,10}
{3,8,3,22}
{4,15,8,33}
{5,73,26,243}
{6,195,91,523}
{7,561,351,1431}
{8,1764,1475,3344}
{9,7814,6657,11642}
{10,32043,31991,32043}
{11,177565,162581,111453}
{12,944493,868779,3966b9}
{13,17527045,4858932,3828943}
{14,28350530,28333238,3a9db7c}
{15,171759007,171699980,1012b857}
{16,1078631835,1078354969,404a9d9b}</pre>
 
=={{header|Nim}}==
{{trans|D}}
<syntaxhighlight lang="nim">import algorithm, math, strformat
 
const Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
 
func toBaseN(num, base: Natural): string =
doAssert(base in 2..Alphabet.len, &"base must be in 2..{Alphabet.len}")
var num = num
while true:
result.add(Alphabet[num mod base])
num = num div base
if num == 0: break
result.reverse()
 
 
func countUnique(str: string): int =
var charset: set['0'..'Z']
for ch in str: charset.incl(ch)
result = charset.card
 
 
proc find(base: Natural) =
var n = pow(base.toFloat, (base - 1) / 2).int
while true:
let sq = n * n
let sqstr = sq.toBaseN(base)
if sqstr.len >= base and countUnique(sqstr) == base:
let nstr = n.toBaseN(base)
echo &"Base {base:2d}: {nstr:>8s}² = {sqstr:<16s}"
break
inc n
 
 
when isMainModule:
for base in 2..16:
base.find()</syntaxhighlight>
 
{{out}}
<pre>Base 2: 10² = 100
Base 3: 22² = 2101
Base 4: 33² = 3201
Base 5: 243² = 132304
Base 6: 523² = 452013
Base 7: 1431² = 2450361
Base 8: 3344² = 13675420
Base 9: 11642² = 136802574
Base 10: 32043² = 1026753849
Base 11: 111453² = 1240A536789
Base 12: 3966B9² = 124A7B538609
Base 13: 3828943² = 10254773CA86B9
Base 14: 3A9DB7C² = 10269B8C57D3A4
Base 15: 1012B857² = 102597BACE836D4
Base 16: 404A9D9B² = 1025648CFEA37BD9</pre>
 
=={{header|Pascal}}==
Line 1,054 ⟶ 2,278:
Than brute force.<BR>
[https://tio.run/##zVdtU9tGEP6uX7EfMmMJZCMBIYmNmYGAGzcJThOntM0wGb0c9lH5ZKQTlMnkr5fu3p3ebDfTtM1M/AHkvX27Z59dr9LwmkWyuwzyKEi6V8vo4WGZpbMsWAD@pzN/YO3sjLiIQc4Z5IsgSVguQRSLkGUgQKYQBjmD0IU8RZ0Az7YEcBElRcxyQH10EPMZlzmkV0bZ@vRoPDo9G8HozfPPnx69npyewenZqzcvxvjt7Px0PPpsFTnLLYD8Pi8kT/KBFaUilxZE8yB7xyT0Iciy4P6D1@vtHVySbzqBYcfzd/f2Hx88efrs@OQ5BvnhxfjHl69en0/e/PT23fT9zxe//PpbZwBgyfslwwjyvFjI9IQSG0LGojSLAcUrHyHDj/GsHdbv7qvA4b1kg80mkZDu5hNEAtDbBYZbs2UCZbdBhnJMjhzkN9nuCT3ELJEBCsm2znywFgKvYF0VIpI8FfCaC46l@yhswr9/Hkh@y95zIZ0@/T3Ypyp3wPfWkev1eh2TCseQtenAOmEzLlCesbxIEJmhqi6msrMDwe8BdHyvg8fjka76EewSiYQGd5Rm5HBIQs2hrg9xapCoXeqnLVLY5oNWNJnh/WxERtpa6Gx7vWf0cSo8LAUlWEjniMVFxuB5Km53kb82Xop43G@gKEo4VmEqq3FTpBj6/VhjpiBpIAIVJOpmnk53yQKprqWNh9g1Mb/VWCk5xu8Zen3gl0qjS7pbtYogKcn0V2wvmzv0XAhsDjw20UpXSDuy4E0ZEa6skUVFihKGEBTLJXay7lCrURdOdZnz2dyuASrTdLBSpkfWk8dE1kCfFOTEVi28AnqFbU2vcZNdd1zOyUSTo5Q2EvWfdM2VFYPuBObt1QnCXcYlszvQcQZtw41WLSMzaz7UF7xUTuh@m7g1FhHe64TPFLmCOPbb7DJcGStG7ewsM5axm4LnGCvH71QaHJnoSA3bYMFc1e6tvivRcnM3dCMcRvebcQvpipRCWfxBi5fG0ny7m/OEIY2OSgxqnPOWH43CtrLeRgMc3RBqXCuPkyy286NhaPBWDvIu2F2tcXyOJuZsxa/SbDDedMoq6TX8NOHKzLXnw69K/1tkvTlHnICVCXXmITUXTsK2s7pn/4ZXG0mlsutX9V/nVR820EpfezjU9DpUKk1i/StKffel@O@FOI7jZiFc/LPbnmX/qKvJ9ohsXeUGDjUu2ySqxqFu7q@sRrutq1Hn0TAn773m0CNIwi@Xp7L5tuUyAxVKPjVTXaUWTvz/i1m4qGRskd4y2uL4FeRHoV5RwnsIuezKOx7HCRez728kTHENb25z48aWgrMTzCKjaM/da5f09dq86TdW/dopb49Vqmr6trdGJa@WJ72P4qrvrp/RytqQVxsrDfRiQSLTRuWJWz4ofTPsqkPfaVFjdavCPSbFLQjwfSGu1xiA6sLGRHfDtaoMJd/70s9/w7h8nLwF24d8njTMqdjXl05daKOsMwZVZmOk4BiWzupa4@fk7dnxSzOh6D6C/SExSEEjQ79oqQMDmka@hdg6ZrvO5kXxKkj09ldvKhjB1SpmSVNeVTJGoCIqjQviSSJs3vf3ncYGpGk39fowPQ0km/KFCqLW/r6o@EZXLOfN1FN8SO8GJf/Qb0dZrL0tlQ8aE1s4UFcJK6gXO6quDmjeKfyDsp5VrzjNYDYG7049Z@vpwb7n9X2vv6fOy3fTi/H56eTi3eeMBXEiBtWLKd659/DwZ3SVBLP8oTvZ@ws Try it online!]
<langsyntaxhighlight lang="pascal">program project1;
//Find the smallest number n to base b, so that n*n includes all
//digits of base b
Line 1,242 ⟶ 2,466:
writeln((now-T0)*86400:10:3);
{$IFDEF WINDOWS}readln;{$ENDIF}
end.</langsyntaxhighlight>
{{out}}
<pre>base n square(n) Testcnt
Line 1,264 ⟶ 2,488:
===Inserted nearly all optimizations found by [[User:Hout|Hout]] and [[User:Nigel Galloway|Nigel Galloway]]===
I use now gmp to calculate the start values.Check Chai Wah Wu list on oeis.org/A260182<BR>
Now multithreaded at bases <> 20 .Inserted StartOffset to run later on.For bases> 28 an intermediate stage of the minimal advanced thread is saved every minute.This is the candidate to start with again.<BR>
GetThreadCount needs improvement for Linux<BR>
Now 2..28 finishes on [https://tio.run/##7Txrd9tGrt/9K@Z0e65Jm7Iedm1XitO1LKvRXb9u7DTdm@P6UBJl0aZIhaT8aE/@@s0FMA/ODCkl3pvu3Q/rNraIwWBmMAAGwIBKhnfBKK/N/WzkR7XJfPT58zxNblN/xuAvtjU7a/V6P4zHLJ8GLJv5URRkOYsXs2GQspjlCRv6WcCGHssSwPGhbSNmYTyKFuMgY4APBMbhbZhnLJkIZObf@2zuxwT3o7U/vh/0e8d91r84@rTG2B/fn573jlnv@OTizYADzud5OAt/9/Mwidn5mXd4cvKpXr8Igvk0iQIvDW4f/NQ7ujz2Di9P4Q/vdQRkDk8GP5/hckYHzV3v6Pzs8up0cHaw3fKgxyyM4RNQipJkftD02CRJ2dvn34MY5nQcSTqHFxdXf784Ztj7/ASA0HjWG/Q/rS2yICMUvoB3Z4Nfscson6aBP848ahO4jN3O5l69jkwDfo8WkZ8DT3M/zdmDHy2I0uVz9i4Po6yztpY/zwOA5G@DW1j17g47YI2trd3tDgIvk@gyyAmYBTmyVuFR@6mf3VOrn6b@8wfVeI2ogzgXaHOF95voAgMD/Gwx6z7nwWD8xEd1dndqDbfW7IhGbOAtb8LbqaPhu6w3@IVdhr8HycQ5gw17CN6Fce5ST5gMYBaz4pRoTgIVpqZmkCddEJcDlgajJB0DUP7E@fBmfJvDp7ak2bGacTENzwJegewC17w4796MF7PZM/TXxzWxR3FuEwDx9cpYw7wERa4gQ2CAIfwpSAfxmK@vd5u/TZL88mMK7Jj7o/tgrC90nGY3J2GWtys3sKCJeLCk8wkIRLsQi6IRpty28RG1BDqKcxsKc2wdjsc2@CwIxtl5HJwmadBDFQaEBNTQjxFHrfAomQ3DOOgnKeBekUIwYzNHk/wm@5i2hp56HAdR7p8FT8gXC9rWZKKjmkbJIs6ByyhjctkI5@MNemqDQ7nBResbsEBRUMao12ECAdq8hP3QbNHqi7kIueHbAgoAGLVmbXvDQZk/nzjFLN2aAGlq4Br7R7xibM7n042S0T2pYgXruFYvojxkFRoBP7ObSzQlySQT7NhudWwMzq3qdprLKImzfA1Z0GTZNGINj21tefzz7jZatsOz3g23FO3Cyjhr3/fNn2PPhvRKkG4JsufZhI77NlKvBOmWIHt9m9Bx30bqlSDdEmSvbxMCOhZSrwTpliB7fZsQ0jGReiVItwTZ69uEiI6B1CtBuiXIXt8mxOnoSL0SpFuC7PVtQoKOhtQrQbolyF7fJiTpFEi9EqRbguz1bUKKjkLqlSDdEmSvbxMq6EikXgnSLUH2@jYhjY5A6pUg3RJkr28T0ulwpF4J0i1B9vo2IYMOIfVKkG4Jste3CZl0EKlXgnRLkL2@TciiA0i9EqRbglh0@mvkboymfgqnoWard7fJ/B7GWXgEjeyADOB6o9na3vlhd2//x8PuEfhxP78Z/OffTk7Pzi/@6@3l1btf3v/69//2h6NxMLmdhnf30SxO5h/TLF88PD49/7613tFcwKOLd7s76OyhbWyCrf5@v2H@16HGp26YHzDuzWkuokYGHNMqMnr37abRHXxLRkdEq4mekTwtnNlNMpmAm9je7czEYeq0vH0P/rnEqepO8jyhbnR0tHcI/f3h4Orm9BKwmvt7P3TgtABeB3B2BQ9B@sye2Cxj4YRNwjjMpuDXbGy3AHe3Aa4qHDBj9HPBnQ/6/gjAgli92Wg06oDTAWoOCxkcNLA@5qKbuQZL@8s3/AFyg3i@kH438zNGJ58f5zi5k@QEoo0cRqYj8k2oHvdxdnAss@1WDXYAt4nN/CcNZbuFzs@oH0bBmT8LALKObudN66a1v5U/5etAYb0@Dh7qZ@9OTugphqGDOOOtdPgyiCvYFPz/lAcSYXzL2QABAm7K@SQD3kPfHEjTzmxc5sH8fTjOp7grzcb2/v5OY3tvf3t3v/OtmYceC8RTwXiRBgz8Q3B4HAimmD8eNw0vjTMV4S0d7nYwznr0U3QUoSOPsShO4zKvuUOZ0F6KcJa4RWZncH@yaZLml3kKbMN2GBjCU3A0ux4zHExW6ViiZ47Nbd1Jx4Yr7wr8oStY41UPQrcrEGEE3w4jPpcj3Aj0WvtC8HU/a4LKBeOSbzxZxCMKZX8Ocq2vHY0MweePyURJs/AeQvHkMfskHbe3QQb6ytoHSOloviAyHdHl@IQHsCZiC8RGRwZpCzMWJzl7TNJ7lLRFPIbg/iSMF0/sp59@ktSkiZIOfiED5wuxChRCJ2yPk8UwCjpXU4wp@JJwRZkUUU8I8YSsM0WjZFe4LDB250FgrmIzFZplXjZps0tzc7uKR1mewtj77ZaXuaIDrjfbXGdIbl3AlJ5AW42muKFgHIUGB3XjT6jtd/SM8QB1qDXZOBGMHUwI/7UhtB/urreK6CSfBrHytAXx5egdtRg1rQ3otKnzrLkLrDAXmU3442Ma5kEUO5IH8nmiuNKPFtnU4d0r9xL1mWtuvJgZ2oFanhlbYOzbvAubNu@qYDG0trCQ58cQNgCoSz4WLZzKAfurCPI/NK5lmBIiXMTcG@XQSqI9TsH2ApUP4TUazWKrIHoNRk6oEAd9IPkK91XfoFDbe0YJIYKEQOcxBgkwCArmC0/jAw2q5qvET4ieiPbg/MQ9UTvEnyYeZyiAV@6MsEUFw2iUdTRyMI7YPbR4hhKso/0r2rkxtESko0TF7VTJiDJatwEZxuVy4lr7/nL5kDKwmG3ZcrBKdAorV95AUl9JkGdtWI019d0cxCOHk/C4/ChRKQiLT7NkzByREkIyrrHF5c078qNRcZo4mAfVrb2hRkfTe81tNTM/VoYHUClvszpJFHrsrpzpukC/xMoZFcxUfIuSR4cP4yIHKd8nnyu2gDeh7um7wJckoB@uLX2Yoxujt9Aey3O4apR6naePcz9iIovMUuAtczKQDD8SUJVzdvmG4cda0xVERHoMBx6qpBJDz/V8PHZ4N8M0iEyZ7ABjPLCWaA2iLKhCbJAg0Pyxi@wKItNRa8FsMJqt0ZRhWpMWQvn2jwsfZAe3HZ5E0v0xhNUNwZGeBZUiLskbdk9kE8UGOCHbYCHnib7yej0L/HQ0RScAiWZJtECNXzNWdRSv0rCq4YGj@gwOFH8M7ur7S734JYJD0uGxwm5LVS3m41oJVrkcGBgdmwmcq3SDEbNS7lJbW6kNF6UtWluzWFG5h7Yicz0T6UY0kUtdEp9EW5DJxXK7ycU75KJkANuUm9k9vDw2mVrF2C8yV0dQmgs2pISEu6AU3mrVNkIcqs3iOQ3mgZ@vGYsLYUw2R6NkL6G8AC07TYezOXT37fHh33SQMRc@bX3F4HWFEYz/2tCGwndaDyFAS3O2rjNK0Vxq8@FsfLhZhDeguKbBx0wzW4Qqa42WHw9wM0j6moPz3Ys8K1PGpvLmhg8oD1pXlzt5@FrmfKmLJk9Ey6SqGxmyPjylkU1TtuduOK0fdmtqwdZNDaJzHjlNl5LQ3Lw0dVxxluvzE2ADBhK2AHfvtenvmaJl@n4VYsq9SkACUrb1JEkKRSMeDXZjtdgtQmaMaS4pNBuKe6UDmkuteV3qyb1VeQtn@shss8mWCfASCW6dVYpvhchyIMQHs/nvN6ZLk8/mAtx5qUBjL4in85ssyB2go9zWl0rzmeZMGvIspPnshc7mP1vWTeG0RFMJJjEZpO/mI5ge4hejX0N9WFsWuSRi19Fsrvo1XGbp1ArxWyK2XyeTlj9IE4nAFcF5LImGKBz@BdN3RxBIQwBV6VKDb0Wt5ECBJ4uHS1F4IF2q75oNTABvbW11yUFk360ptwxCpRy1BjqROuA5ELM4eET5m/n5libl2QPeZ3rw14OPPt6cajJ/77HxMIJTy7xxrBR2J3twOzYEibvCndS14iYLHTk03@Z6HZb0HY8QyoGHpAEWUfrYW1/wZnS554vAHTV6i@NY95A4Irk8q9yie@UWVTmP9uGPK58tIpTSgt/64i1c2IYq3PtqnxE@lh36JVNu4ZTFIv/fJqzNR0zlX4WPSqnXDHbaDknByvKszTl//Yy/ar7m@ae0ChUeeskeVhptnewOO6f7FHAIZTrelaUDIkO7u4PVPltjiNVgjZM0CHiVFawt4NlWTPFze8@SOHoWqeKycvM1wGrUWHScbLfUkPAcTnIWBfBLo4CsagVPc9ld/FEdTSZpGHwmjlqaiS94Q/yBR60RBtTYjf@kpTH8CE8k5KWFsxpFor5s7viJUBpVgYvN0sECZCTPShmt46c89UciiQ2HisM/naVagoq5epWJ5XAb2VzZ@brKa6CCFxR5Vf1SzjFZuWCzosXwAuxiFq3RDEvUUo/wou5CHYEygVeZvqMDKoyjMA5WRSNURNZWxWRfyu3xNK6WhjO8sLjkgxFZatOKT3hTqljGuwlXSqgs5YEhqjtgO1U7Qclgb8ctPCpJjEakZO5m4/qabiJ540rU5tejtr4edbsCVVkuipqNiMZwC6sIVo6s58VFMPyqUe13geOIxX7h7ZIrv1hqyeoAFhTcw6rRkZ@mz8udf9IUHGRLeNudNdsVJgplb151Mtx5EomYWFalm9KvvWabgu4mYFOgpzRODneegilE4Rq6ZsIfjjCnxtHQaSyalY@eKe@YRJcHi@pWQvPMi5OJz5xTffXV0/9TJl09QRBFxXIRB7yCfVKC2dUmaiPqAYPeVkQNTkUlnRU2VIrqJVYsr7iftqVPBA3zNEiDj4swg0M/k1wnJ6OQ6SUi/WJZXiWvupz/K0vAny8AXw4by/t/Cg4QRHjo4OD2x@beF/k3w1KBE20XBBQchkbS2MJxkfm9WG6qhzWTsavv2SJcZnCAZ@9CYnezlJlisrQiprhRbYeAAsiEG6mn1tdcR2HxA8aE1Xe9lMwZx9lHGCbKy9W3cVWwjRGzUWNBDmq8AcRNRgJd4qSs3Nb2io8pWSiXyycCvwW8OIcEPttQfYyNEVkd2poWIuE/WtOSzMIFnKF@KupLMiefisIOdR1flDSIZVMNP16aYJZBlP4zn1jqwb/NovBha4sAimit6RbVB4JWMOdZJ4gRimKF4QKjcd5J61Gvi9T0LhV/7WJtL3g78KG5w5q7ZgYOpwN/uIMNH4xaGPnM2rjRV9pGEzjTquj26HpRLyHmRWOyekyeCB6/8TL9wMIM8BkZUiBnR9YGPyiwIVMY62rPJpJqFXLSZ0VpFOhYs9oi9Y1kYrE9RSzaNWJRZHyY636/anpfCgjC61WBuAoEcHjJgY6FIOrcjUwxM9VY7HCpjF4BvLIALcsp1OvYm4oGRI4sjJkuqOogUCesGL6KtNDhZbKnpyX7pQCFurgHjdWXhSo@V5eW4tZv3UhkGGGgnfGxLnH1eVeqivvlZIcuNEJJDmS1Zce6FwayZ4WxKvK@/xbNf4vmNxHN4rj7P5Zv8hpVxs4aFEvO6I6j9FN7zfYbrNHA3/x/@iw6O3pn99fztyYZ6NyQfRoN9Zl3dpZ0dvlFi@jcaBad6bOc9pKfjXttZHZfdAY4dOYH6RwY1vTwd4u15@abQ7gJR@hAe7F375027FDgtOmF1htnUnNBuHS/96BwBQvdRgQRQohj9/jXwZX2GhEn0qogIlFpEkCjmDe/oOJF4A09PkGG8toVyr1gMZFz2uD5OLJGh9pQHcGZFkYyqqGIZIhros2McnS2KRuiJTHq9TE8xOBPAVYazKJnBvqDrkh8G8yCmO5fRCBNM/ht87SxqUhu0si/iQgFwhbCEdphDOzEJDy8st5lKFPCAvMgvQZkHQewUO5OudDBH3b55i1e7d2LYI6Ggw6xOaSsDysSLbLmQFYIVfIUdrSYpB4gFFJhJHwUG5omG6Q1@MoVv2zN5VXzdRfXizYX@NqLyYhtF2JM3i9iM340FWulgs3X6k6x0pEzbhw7a5WX6oeaqq0oJBXhm3NoRauv8WYUWeJISbYwqO7UqKOgjbewinGQP0sakSfwR3Kn2nxfhrN5FLzQiBd5XTCKOPp/kFEjKcOIlITxFbX8ubbvhRbpn2yQigeUfkOjDDNV2CdpsL5kpwojBWqm26mX2KVV6onqG3coMHyJPttmUk8Or7Zvtk37CvNVuXN/qlVbxYBNZNE3tWp/8AQIvhgFi/JH02CsmzJd66vt2aGdDutUNLzErimPcIN9Ms2KngTBm5S3i/hqOnbmfurPgjxI22yeAJ0gNRJmofny9Ry6dKP7tvFSs1XczVEo7WkEI5oRUIO6eiWO6PlbZS5tVXmM/jZaOdFWqhjEHaMYg@pveZhhhQzC5hbvsJfeXy9FGVoX8zUkBVlaoGNFWrXQrNwpXerJWUFwohVkKBYcrCqCG@AWnyT4jQQwiZSslyO7LptRuLSqjB3HY77LTmNJxg2FzajfsSvii9SbIWtY1@69ywJBPzPfK1py/XhFhVlx8shpVNYRuVobJ8ewk7wR1/JiWkpKZbFkyrL8qpkpGXqIaiJLk2K8rNRUeXaHyoNfsx2XTmrMFDqrK3nc6lIe8d0ukzAtvtSF16GPfHrPg5ehm2XgpIlwXKZ5VhTnF@6SqlHWXxMB2u41ah62Ar1VSQedLRi2K24YkW/F@3x2gfgS5raqMwsGrzmH8b0OSqcbzOXV4JpaFT03qjBx2Ro9w/JUbbCak5FCQU4Y6@B5Ez2nYVwZ8RJJqfCFabzTPmuqg1DzRUYlbZSfesVahsmwuoqpW6lzXTVLEy1eTFsn5qzzKh6PrTN6HYS/SwzQInu@rpLrB9CgUbfepBJFOqy9blfvfNuRSuNoORylq1VJo6H76nVjiU6KoOMOWK6PS5ru6BbcXVYnVa5Iuftils8qItGPRsQWBvyvhVvgsQvuDDh3rmcUqHjWSwI7GzuNH3eXpfPwnLsrp6tKEnan3qNZedCDXzXkxrG1b6pa11q1eqV2cPZJA7/3w7yfpHzkqwC/IgpPBYOdDf66ps4zT7zG7hoj6G/gkrpHQTB3qlHl67VfTP39ozOs6XY0tNwL4JszIBnbbrq2fyBEW3/Hd0O8wO9V6rh@EFtFxoYbpvb0H10T0xZlSUIv0AXr5VqxZEorp0BWO0oyYQFLyAZiKL6Iy1GOlMsqXFPTit9VqhFn7R0zi7@K86BU32a5c3QohBvaXm5KjE69jkpPRwL/sjK62kxSMGcxL6G27mPxpLor5fGvmobbpUy1rHpbNy2rDbay4@/V4eEA4RrLwRpusP3dnUajzX5ss2007hk5lvIbota9uzZr7sDU1H1gu7nvmvS@LTWNnxurKK9rfjF3eUvvW6xJ8ZS01TdMUN/DLAtvYwQBS8wmsHM1blcO55iYEG/1AnjzE4/RB4ng9iurlOyRb5Jb/pYD/oUDlrdQXHQczRfsSHHK6kvksiCPgvg2nxo67rEyLn7xgiY6WDIsb8zk93TQa6n8o1BoFVHQYFc8MZA81q7cDWK@Md1RgnFZDgqGXxPgsas2a8it4V9YwjdI81isLst6kC0gBq5YcsPVvz8GjqPe@fvLT5Rf8sdRbHzDC@zf1tra58//M5pE/m32uXa@/bl2@fC/ Try it online!]
 
The runtime is on my 6-Core PC AMD Ryzen 5 16002200G ( 3.47 Ghz on all 4 cores Linux64 with SMT= onoff)<BR>
<syntaxhighlight lang="pascal">program Pandigital;
 
{{incorrect|Pascal|Seems to have a bug. Value for base 3 should be 2101, not 111}}
<lang pascal>program project1;
//Find the smallest number n to base b, so that n*n includes all
//digits of base b aka pandigital
 
{$IFDEF FPC}
//{$R+,O+}
{$MODE DELPHI}
{$Optimization ON,ALL}//Peephole,regvar,CSE,ASMCSE}
{$CODEALIGN proc=168,CONSTMINloop=32,varmin=321}// Ryzen Zen loop=1, for Ryzen
{$ElSE}
{$APPTYPE CONSOLE}
Line 1,283 ⟶ 2,506:
uses
{$IFDEF UNIX}
cthreads unix,
cthreads,
{$ENDIF}
gmp,// to calculate start values
Line 1,289 ⟶ 2,513:
 
type
tRegion32 = 0..31;
tSolSet32 = set of tRegion32;
tMask32 = array[tRegion32] of Uint32;
tpMask32 = ^tMask32;
 
tRegion64 = 0..63;
tSolSet64 = set of tRegion64;
tMask64 = array[tRegion64] of Int64Uint64;
tpMask64 = ^tMask64;
const
// has hyperthreading
SMT = 0;
{$ALIGN 32}
//set Bit 0 til Bit 63
cOr_Mask64: tMask64 =
(1 shl 0,1 shl 1,1 shl 2,1 shl 3,1 shl 4,1 shl 5,1 shl 6,1 shl 7,
1 shl 8,1 shl 9,1 shl 10,1 shl 11,1 shl 12,1 shl 13,1 shl 14,1 shl 15,
1 shl 16,1 shl 17,1 shl 18,1 shl 19,1 shl 20,1 shl 21,1 shl 22,1 shl 23,
1 shl 24,1 shl 25,1 shl 26,1 shl 27,1 shl 28,1 shl 29,1 shl 30,1 shl 31,
1 shl 32,1 shl 33,1 shl 34,1 shl 35,1 shl 36,1 shl 37,1 shl 38,1 shl 39,
1 shl 40,1 shl 41,1 shl 42,1 shl 43,1 shl 44,1 shl 45,1 shl 46,1 shl 47,
1 shl 48,1 shl 49,1 shl 50,1 shl 51,1 shl 52,1 shl 53,1 shl 54,1 shl 55,
1 shl 56,1 shl 57,1 shl 58,1 shl 59,1 shl 60,1 shl 61,1 shl 62,1 shl 63);
 
charSet: array[0..62] of char =
tNumByteIdx = 0..(64-0)-1;
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
tNumIdx = 0..High(tNumByteIdx) DIV Sizeof(NativeUint);
type
tarrNum = array[tNumIdx] of NativeUInt;
tRegion1 = 0..63 - 2 * SizeOf(byte);
 
tNumtoBase = packed record
ntb_dgt: array[tRegion1] of : tarrNumbyte;
ntb_Mask0ntb_cnt,
ntb_bas: Byte;
ntb_TestSet,ntB_dummy : NativeUInt;
end;
ntb_cnt,
ntb_bas,
ntb_cntbts,
ntb_HighByte : byte;
end;
 
tDgtRootSqr = packed record
Line 1,323 ⟶ 2,563:
cft_delta: tNumtoBase;
cft_count : Uint64;
cft_offset: Uint64;// unused but doubles speed especially for base 25
cft_ThreadID: NativeUint;
cft_ThreadHandle: NativeUint;
//extendAlignment to= 512 byte32
//Base 25 test every 12 0.539 s Testcount : 78092125
cft_dummy : array[0..512-1-3*(SizeOf(tNumtoBase)-SizeOf(NativeUint))] of byte;
//Alignment = 24
//Base 25 test every 12 1.316 s Testcount : 78092125
end;
pThreadBlock = ^tCombineForOneThread;
tMulti = record
m_Startofs : Uint32;
m_count : Uint32;
end;
const
//1 shl 0, ..,1 shl 63
cAND_Mask64: tMask64 =(
$FFFFFFFFFFFFFFFE,$FFFFFFFFFFFFFFFD,$FFFFFFFFFFFFFFFB,$FFFFFFFFFFFFFFF7,
$FFFFFFFFFFFFFFEF,$FFFFFFFFFFFFFFDF,$FFFFFFFFFFFFFFBF,$FFFFFFFFFFFFFF7F,
$FFFFFFFFFFFFFEFF,$FFFFFFFFFFFFFDFF,$FFFFFFFFFFFFFBFF,$FFFFFFFFFFFFF7FF,
$FFFFFFFFFFFFEFFF,$FFFFFFFFFFFFDFFF,$FFFFFFFFFFFFBFFF,$FFFFFFFFFFFF7FFF,
$FFFFFFFFFFFEFFFF,$FFFFFFFFFFFDFFFF,$FFFFFFFFFFFBFFFF,$FFFFFFFFFFF7FFFF,
$FFFFFFFFFFEFFFFF,$FFFFFFFFFFDFFFFF,$FFFFFFFFFFBFFFFF,$FFFFFFFFFF7FFFFF,
$FFFFFFFFFEFFFFFF,$FFFFFFFFFDFFFFFF,$FFFFFFFFFBFFFFFF,$FFFFFFFFF7FFFFFF,
$FFFFFFFFEFFFFFFF,$FFFFFFFFDFFFFFFF,$FFFFFFFFBFFFFFFF,$FFFFFFFF7FFFFFFF,
$FFFFFFFEFFFFFFFF,$FFFFFFFDFFFFFFFF,$FFFFFFFBFFFFFFFF,$FFFFFFF7FFFFFFFF,
$FFFFFFEFFFFFFFFF,$FFFFFFDFFFFFFFFF,$FFFFFFBFFFFFFFFF,$FFFFFF7FFFFFFFFF,
$FFFFFEFFFFFFFFFF,$FFFFFDFFFFFFFFFF,$FFFFFBFFFFFFFFFF,$FFFFF7FFFFFFFFFF,
$FFFFEFFFFFFFFFFF,$FFFFDFFFFFFFFFFF,$FFFFBFFFFFFFFFFF,$FFFF7FFFFFFFFFFF,
$FFFEFFFFFFFFFFFF,$FFFDFFFFFFFFFFFF,$FFFBFFFFFFFFFFFF,$FFF7FFFFFFFFFFFF,
$FFEFFFFFFFFFFFFF,$FFDFFFFFFFFFFFFF,$FFBFFFFFFFFFFFFF,$FF7FFFFFFFFFFFFF,
$FEFFFFFFFFFFFFFF,$FDFFFFFFFFFFFFFF,$FBFFFFFFFFFFFFFF,$F7FFFFFFFFFFFFFF,
$EFFFFFFFFFFFFFFF,$DFFFFFFFFFFFFFFF,$BFFFFFFFFFFFFFFF,$7FFFFFFFFFFFFFFF
);
charSet: array[0..63] of AnsiChar =
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.';
{$IFDEF CPU64}
Mask1 = $8080808080808080;
MaxBit= 63;
{$ENDIF}
{$IFDEF CPU32}
Mask1 = $80808080;
MaxBit= 31;
{$ENDIF}
// Multi21 : tMulti = (m_offset:6;m_delta:(2,8,2,8));
Multi21 : tMulti = (m_Startofs:6;m_count:4);
WAIT_MS = 1875; // check every x ms if finished *32 = 60 seconds
timeFac = WAIT_MS/1000/60 ;// ( i AND 31 ) = 0
 
//############################################################################
//Input values as constants
LoLimit = 2;
HiLimit = 28;// For 32-Bit CPU max HiLimit = 32
 
cFileName = 'Test_2_28.txt';//'/dev/NULL';//'nonsens.txt';
// use hyperthreading = 0
 
StartOfs= 1;//testcount*StepWidth = 11038840378368;
//############################################################################
 
procedure AddNum(var add1: tNumtoBase; const add2: tNumtoBase); forward;
function AddNumSqr(var add1, add2: tNumtoBase): Uint64; forward;
 
var
{$ALIGN 32}
ThreadBlocks: array of tCombineForOneThread;
{$ALIGN 32}
s :shortString;
Num, sqr2B, deltaNextSqr, delta: tNumtoBase;
{$ALIGN 32}
DgtRtSqr: tDgtRootSqr;
{$ALIGN 8}
T,T0, T1: TDateTime;
gblThreadCount,
Finished: Uint32;
 
f : text;
function GetCoreCount:NativeInt;
// from lazarus forum
var
t: Text;
s: string;
begin
result := 1;
try
POpen(t, 'nproc', 'R');
while not Eof(t) do
Readln(t, s);
finally
PClose(t);
end;
result := StrToInt(s);
end;
 
function GetThreadCount: NativeUInt;
begin
{$IFDEF Windows}
Result := GetCpuCount;
{$ELSE}
Result := 12GetCoreCount;//GetCpuCount;// is not working under Linux ???
{$ENDIF}
if SMT = 1 then
Result := (Result+1) div 2;
end;
 
procedure OutNum(const num: tNumtoBase);
procedure OutThreadStep(i:double;ThCnt:NativeInt;stepWidth,StartOffSet: Int64);
var
j,min : NativeInt;
s,sf: ShortString;
Begin
str(i:8:2,s);
s := s+' min ';
stepWidth := -ThCnt*stepWidth;
min := 0;
For j := 0 to ThCnt-1 do
If min > ThreadBlocks[j].cft_count then
min := ThreadBlocks[j].cft_count;
str(stepWidth*min+StartOffSet:16,sf);
s := s+sf;
writeln(s);
writeln(f,s);
Flush(f);
end;
 
procedure OutNum(const num: tNumtoBase;var s: ShortString);
var
pB : pByte;
i: NativeInt;
begin
with num do
begin
pBfor i := @ntb_dgt[ntb_cnt - 1 downto 0]; do
i := ntb_cnt*SizeOfWrite(NativeUintcharSet[ntb_dgt[i]]);
while pB[i] = 0 do
dec(i);
IF i < 0 then
i := 0;
for i := i downto 0 do
s := s+charSet[pB[i]];
s := s+' ';
end;
Write(s' ');
Write(f,String(s));
end;
 
procedure OutNumSqr;
begin
s := Write(' Num ');OutNum(Num,s);
s := Write(' sqr ');OutNum(sqr2B,s);
writeln;writeln(f);Flush(f);
end;
 
function getDgtRtNum(const num: tNumtoBase): NativeInt;
var
pB : pByte;
i: NativeInt;
begin
pB := @num.ntb_dgt[0];
with num do
begin
Result := 0;
for i := 0 to num.ntb_cntbtsntb_cnt - 1 do
Inc(Result, pBntb_dgt[i]);
Result := Result mod (ntb_bas - 1);
end;
Line 1,519 ⟶ 2,700:
Inc(i);
until i > base;
writelnwrite(' insert ', i);
end;
end;
Line 1,526 ⟶ 2,707:
procedure conv_ui_num(base: NativeUint; ui: Uint64; var Num: tNumtoBase);
var
pB : pByte;
i: NativeUInt;
begin
for i := 0 to high(tNumtoBase.ntb_dgt) do
Num.ntb_dgt[i] := 0;
with num do
begin
for i := 0 to high(tNumtoBase.ntb_dgt) do
ntb_dgt[i] := 0;
pB := @ntb_dgt[0];
ntb_bas := base;
ntb_Mask0 := (Mask1 shr 7)*(256-Base);
ntb_TestSet := Uint64(1) shl base -1;
ntb_cntbts := 0;
ntb_cnt := 0;
if ui <>= 0 then
begin EXIT;
i := 0;
repeat
pBntb_dgt[i] := ui mod base;
ui := ui div base;
Inc(i);
until ui = 0;
ntb_cntbtsntb_cnt := i;
ntb_HighByte := pB[i-1];
ntb_cnt := i DIV SizeOf(NativeUint) +1 ;
end;
end;
end;
 
procedure conv2Num(base: NativeUint; var Num: tNumtoBase; var s: mpz_t);
var
tmp: mpz_t;
pB : pByte;
i: NativeUInt;
begin
mpz_init_set(tmp, s);
for i := 0 to high(tNumtoBase.ntb_dgt) do
Num.ntb_dgt[i] := 0;
pB := @Num.ntb_dgt[0];
with num do
begin
ntb_bas := base;
ntb_Mask0 := (Mask1 shr 7)*(256-Base);
ntb_TestSet := Uint64(1) shl base -1;
i := 0;
repeat
pBntb_dgt[i] := mpz_tdiv_q_ui(tmps, tmps, base);
Inc(i);
until mpz_cmp_ui(tmps, 0) = 0;
ntb_HighBytentb_cnt := pB[i-1];
ntb_cntbts := i;
ntb_cnt := i DIV SizeOf(NativeUint) +1;
end;
mpz_clear(tmp);
Line 1,585 ⟶ 2,752:
//calc sqrt +1 and convert n new format.
var
sv_sqr, sv,sv_add: mpz_t;
k, dblDgt: NativeUint;
 
Line 1,630 ⟶ 2,797:
 
mpz_sqrt(sv, sv_sqr);
writelnmpz_add_ui('Startsv, Offset 'sv,StartOfs 1);
//Windows64 gmp.dll or freepascal does not use Uint64 only Uint32
mpz_init_set_ui(sv_add,StartOfs shr 32);
// shift left 32
mpz_mul_2exp(sv_add,sv_add,32);
mpz_add_ui(sv_add,sv_add,Uint32(StartOfs));
mpz_add(sv, sv, sv_add);
mpz_mul(sv_sqr, sv, sv);
 
Line 1,642 ⟶ 2,803:
conv2Num(base, sqr2B, sv_sqr);
 
mpz_clear(sv_add);
mpz_clear(sv_sqr);
mpz_clear(sv);
OutNumSqr;
end;
 
Line 1,659 ⟶ 2,818:
end;
 
function CheckPandigital(const n: tNumtoBase): NativeUint;inlineboolean;
var
pB : pByte;
pMask: tpMask64;
TestSet: Uint64;
i: NativeInt;
begin
ipMask := n.ntb_cntbts@cOr_Mask64;
pBTestSet := @n.ntb_dgt[0];
pMaskwith :=n @cAND_Mask64;do
result := n.ntb_TestSet;
while i >= 4 do
begin
for i := ntb_cnt - 1 downto 0 do
dec(i,4);
result TestSet := TestSet or pMask[pBntb_dgt[i+0]] AND result;
resultResult := pMask[pB[i+(Uint64(1]]) ANDshl resultntb_bas - 1) = TestSet;
result := pMask[pB[i+2]] AND result;
result := pMask[pB[i+3]] AND result;
end;
if i > 0 then
repeat
result := pMask[pB[i]] AND result;
dec(i);
until i<0;
end;
 
procedure IncNumBig(var add1: tNumtoBase; n: Uint64);
var
pB : pByte;
i, s, b, carry: NativeUInt;
begin
Line 1,692 ⟶ 2,841:
i := 0;
carry := 0;
pB := @add1.ntb_dgt[0];
while n > 0 do
begin
s := pBadd1.ntb_dgt[i] + carry + n mod b;
carry := Ord(s >= b);
s := s - (-carry and b);
pBadd1.ntb_dgt[i] := s;
n := n div b;
Inc(i);
Line 1,705 ⟶ 2,853:
while carry <> 0 do
begin
s := pBadd1.ntb_dgt[i] + carry;
carry := Ord(s >= b);
s := s - (-carry and b);
pBadd1.ntb_dgt[i] := s;
Inc(i);
end;
 
if add1.ntb_cntbtsntb_cnt < i then
add1.ntb_cnt := i;
Begin
add1.ntb_cntbts := i;
add1.ntb_cnt := i DIV (SizeOf(NativeUint))+1;
end;
end;
 
Line 1,722 ⟶ 2,867:
//prerequisites carry < base
var
pB : pByte;
i, s, b: NativeUInt;
begin
b := add1.ntb_bas;
pB := @add1.ntb_dgt[0];
i := 0;
while carry <> 0 do
begin
s := pBadd1.ntb_dgt[i] + carry;
carry := Ord(s >= b);
s := s - (-carry and b);
pBadd1.ntb_dgt[i] := s;
Inc(i);
end;
if add1.ntb_cntbtsntb_cnt < i then
add1.ntb_cnt := i;
Begin
end;
add1.ntb_cntbts := i;
 
add1.ntb_cnt := i DIV SizeOf(NativeUint) +1;
procedure AddNum(var add1: tNumtoBase; const add2: tNumtoBase);
//add1 <= add1+add2;
var
i, base, s, carry: NativeUInt;
begin
carry := 0;
base := add1.ntb_bas;
 
for i := 0 to add2.ntb_cnt - 1 do
begin
s := add1.ntb_dgt[i] + add2.ntb_dgt[i] + carry;
carry := Ord(s >= base);
s := s - (-carry and base);
add1.ntb_dgt[i] := s;
end;
 
i := add2.ntb_cnt;
while carry = 1 do
begin
s := add1.ntb_dgt[i] + carry;
carry := Ord(s >= base);
s := s - (-carry and base);
add1.ntb_dgt[i] := s;
Inc(i);
end;
 
if add1.ntb_cnt < i then
add1.ntb_cnt := i;
end;
 
Line 1,772 ⟶ 2,942:
//starting the threads at num,num+stepWidth,..,num+(thdCount-1)*stepWidth
//stepwith not stepWidth but thdCount*stepWidth
//insert 6
// 6 : 4 6 14 16
var
tmpnum,tmpsqr2B,tmpdeltaNextSqr,tmpdelta :tNumToBase;
deltasi : array[0..7] of Uint32NativeInt;
Multi : tMulti;
 
i,base : NativeInt;
Begin
tmpnum := num;
Line 1,785 ⟶ 2,950:
tmpdeltaNextSqr := deltaNextSqr;
tmpdelta := delta;
 
IF StepWidth <> 1 then
For i := 0 to thdCount-1 do
Begin
//init ThreadBlock
For i := 0 to thdCount-1 do
BeginWith ThreadBlocks[i] do
//init ThreadBlockbegin
Withcft_sqr2b ThreadBlocks[i]:= dotmpsqr2B;
begincft_count := 0;
CalcDeltaSqr(tmpnum,cft_deltaNextSqr,cft_delta,thdCount*stepWidth);
cft_sqr2b := tmpsqr2B;
cft_count := 0;
CalcDeltaSqr(tmpnum,cft_deltaNextSqr,cft_delta,thdCount*stepWidth);
end;
//Next sqr number in stepWidth
IncSmallNum(tmpnum,stepWidth);
AddNum(tmpsqr2B,tmpdeltaNextSqr);
IF CheckPandigital(sqr2B)=0 then
begin
writeln(' solution found ');
OutNumSqr;
end
else
AddNum(tmpdeltaNextSqr,tmpdelta);
end;
//Next sqr number in stepWidth
end
IncSmallNum(tmpnum,stepWidth);
else
AddNumSqr(tmpsqr2B,tmpdeltaNextSqr);
Begin
IF CheckPandigital(sqr2B) then
Multi := Multi21;
begin
base := tmpNum.ntb_bas-1;
For i :=writeln(' 0solution tofound thdCount-1 do');
Begin readln;
//init ThreadBlockHalt(-124);
With ThreadBlocks[i] do
begin
cft_sqr2b := tmpsqr2B;
cft_count := 0;
CalcDeltaSqr(tmpnum,cft_deltaNextSqr,cft_delta,thdCount*stepWidth);
end;
//Next sqr number in stepWidth
IncSmallNum(tmpnum,stepWidth);
AddNum(tmpsqr2B,tmpdeltaNextSqr);
IF CheckPandigital(sqr2B)=0 then
begin
writeln(' solution found ');
OutNumSqr;
end
else
AddNum(tmpdeltaNextSqr,tmpdelta);
end;
AddNum(tmpdeltaNextSqr,tmpdelta);
end;
end;
 
procedure AddNum function AddNumSqr(var add1: tNumtoBase; const, add2: tNumtoBase): Uint64;
//add1 <= add1+add2;
// N0 AND mask1 -> 80 00 80 80 80 00 80
//prerequisites bases are the same,add1>=add2( cnt ),
// (N0 AND mask1)XOR mask1 -> 00 80 00 00 00 80 00
//out Set of used digits
// ((N0 AND mask1)XOR mask1) shr 7 -> 00 01 00 00 00 01 00
var
// *k -> 00 k 00 00 00 k 00
pMask: tpMask64;
var
i, base, s, carry: NativeInt;
pAdd1,pAdd2 :pNativeUint;
begin
NextCarry,n,k,M0: NativeUInt;
M1,i pMask := NativeUInt@cOr_Mask64;
base := add1.ntb_bas;
Begin
dec(s,s);
IF add1.ntb_cnt= 0 then
Result := s;
Begin
add1carry := add2s;
EXIT;
end;
IF add2.ntb_cnt= 0 then
EXIT;
 
for i := 0 to add2.ntb_cnt - 1 do
M1 :=NativeUint(Mask1);
begin
M0:= add1.ntb_mask0;
s := add1.ntb_dgt[i] + add2.ntb_dgt[i] + carry;
carry := Ord(s >= base);
s := s - (-carry and base);
Result := Result or pMask[s];
add1.ntb_dgt[i] := s;
end;
 
k i := byte(M0)add2.ntb_cnt;
while carry = 1 do
begin
s := add1.ntb_dgt[i] + carry;
carry := Ord(s >= base);
s := s - (-carry and base);
Result := Result or pMask[s];
add1.ntb_dgt[i] := s;
Inc(i);
end;
 
i := Add2if add1.ntb_cnt; < i then
add1.ntb_cnt := i;
pAdd2:= @Add2.ntb_dgt[0];
pAdd1:= @Add1.ntb_dgt[0];
 
for i := i to add1.ntb_cnt - 1 do
NextCarry := 0;
Result := Result or pMask[add1.ntb_dgt[i]];
repeat
//depends extremly on arrangement.
n := pAdd2^+M0+NextCarry+pAdd1^;
inc(pAdd2);
NextCarry := (n shr MaxBit) XOR 1;
n := n-M0+(((n AND M1)XOR M1) SHR 7)*k;
pAdd1^ :=n;
inc(pAdd1);
dec(i);
until i = 0;
 
i := Add2.ntb_cnt;
IF NextCarry <> 0 then
Begin
repeat
n := pAdd1^+M0+NextCarry;
NextCarry := (n shr MaxBit) XOR 1;
n := n-M0+(((n AND M1)XOR M1) SHR 7)*k;
pAdd1^ :=n;
inc(i);
inc(pAdd1);
until NextCarry = 0;
end;
with Add1 do
Begin
IF i > ntb_cnt then
Begin
ntb_cnt := i;
ntb_cntbts := Add1.ntb_cnt*SizeOf(NativeUint);
while (Add1.ntb_cntbts > 0) AND (ntb_dgt[Add1.ntb_cntbts] = 0) do
dec(Add1.ntb_cntbts);
inc(Add1.ntb_cntbts);
end;
end;
end;
 
procedure AddNumSimple(var add1: tNumtoBase; const add2: tNumtoBase);inline;
// Add1&Add2 <> 0 and Add2< Add1
var
pAdd1,pAdd2 :pNativeUint;
NextCarry,n,k,M0: NativeUInt;
M1,i : NativeUInt;
Begin
M1 :=NativeUint(Mask1);
M0:= add1.ntb_mask0;
k := byte(M0);
 
i := Add2.ntb_cnt;
pAdd2:= @Add2.ntb_dgt[0];
pAdd1:= @Add1.ntb_dgt[0];
 
NextCarry := NextCarry XOR NextCarry;
repeat
// extremly depends on arrangement.
n := pAdd2^+NextCarry+M0+pAdd1^;
NextCarry := (n shr MaxBit) XOR 1;
n := (((n AND M1)XOR M1) SHR 7)*k-M0+n;
// n := n-M0+(((n AND M1)XOR M1) SHR 7)*k;
inc(pAdd2);
dec(i);
pAdd1^ :=n;
inc(pAdd1);
until i = 0;
 
IF NextCarry <> 0 then
Begin
i := Add2.ntb_cnt;
repeat
n := pAdd1^+M0+NextCarry;
NextCarry := (n shr MaxBit) XOR 1;
n := (((n AND M1)XOR M1) SHR 7)*k+n-M0;
pAdd1^ :=n;
inc(i);
inc(pAdd1);
until NextCarry = 0;
{ //never reached
IF i > Add1.ntb_cnt then
Begin
Add1.ntb_cnt := i;
Add1.ntb_cntbts := Add1.ntb_cnt*SizeOf(NativeUint);
end;
* }
end;
end;
 
procedure TestRunThd(parameter: pointer);
var
pSqrNum, pdeltaNextSqr, pDelta: ^tNumtoBase;
i: Uint64;
TestSet, TestSetComplete, i: Uint64;
pThdBlk: pThreadBlock;
ThreadBlockIdx: NativeInt;
begin
pThdBlkThreadBlockIdx := @ThreadBlocks[NativeUint(parameter)];
with pThdBlk^ThreadBlocks[ThreadBlockIdx] do
begin
ipSqrNum := 0@cft_sqr2b;
pdeltaNextSqr := @cft_deltaNextSqr;
repeat
pDelta if finished <> 0 then := @cft_delta;
BREAK;
//next square number
AddNumSimple(cft_sqr2b, cft_deltaNextSqr);
AddNumSimple(cft_deltaNextSqr, cft_delta);
Inc(i);
cft_count := -i;
until CheckPandigital(cft_sqr2b)=0;
if finished = 0 then
begin
InterLockedIncrement(finished);
cft_count := i;
end;
end;
TestSetComplete := Uint64(1) shl pSqrNum^.ntb_bas - 1;
EndThread(0);
i := 0;
repeat
//next square number
TestSet := AddNumSqr(pSqrNum^, pdeltaNextSqr^);
AddNum(pdeltaNextSqr^, pdelta^);
Inc(i);
if finished <> 0 then
BREAK;
until TestSetComplete = TestSet;
 
if finished = 0 then
begin
InterLockedIncrement(finished);
ThreadBlocks[ThreadBlockIdx].cft_count := i;
EndThread(i);
end
else
EndThread(0);
end;
 
Line 1,978 ⟶ 3,051:
var
stepWidth: Uint64;
i, j,UsedThreads,StartOffSet: NativeInt;
begin
T0write('Base :=', nowbase);
StartValueCreate(base);
StartOffSet := StartOfs;
deltaNextSqr := num;
AddNum(deltaNextSqr, deltaNextSqr);
Line 2,002 ⟶ 3,074:
end;
CalcDeltaSqr(num,deltaNextSqr,delta,stepWidth);
writeln(' test every ', stepWidth);
 
// Write('Start :');OutNumSqr;
i := 0;
if not (CheckPandigital(sqr2b)) then
 
finished := 0;
j := 0;
UsedThreads := gblThreadCount;
if base < 20 then
UsedThreads := 1;
PrepareThreads(UsedThreads,stepWidth);
 
writeln(f,'Base ', base, ' test every ', stepWidth,' threads = ',UsedThreads);
Write(f,'Start :');
writeln('Base ', base, ' test every ', stepWidth,' threads = ',UsedThreads);
Write('Start :');
OutNumSqr;
 
if (CheckPandigital(sqr2b)<>0) then
begin
finished := 0;
j := 0;
UsedThreads := gblThreadCount;
if base < 21 then
UsedThreads := 1;
PrepareThreads(UsedThreads,stepWidth);
j := 0;
while (j < UsedThreads) and (finished = 0) do
begin
Line 2,026 ⟶ 3,092:
cft_ThreadHandle :=
BeginThread(@TestRunThd, Pointer(j), cft_ThreadID,
4 * 4096);
end;
Inc(j);
end;
UsedThreads := j;
 
i := 0;
repeat
IF base > 28 then
Begin
{$IFDEF WIN}
WaitForThreadTerminate(ThreadBlocks[0].cft_ThreadHandle,WAIT_MS)
{$ELSE}
sleep(WAIT_MS)
{$ENDIF}
end
else
WaitForThreadTerminate(ThreadBlocks[0].cft_ThreadHandle,-1);
inc(i);
IF (I and 31) = 0 then
OutThreadStep(i*timeFac,UsedThreads,stepWidth,StartOffSet);
until finished <> 0;
 
WaitForThreadTerminate(ThreadBlocks[0].cft_ThreadHandle, -1);
repeat
Line 2,055 ⟶ 3,102:
begin
WaitForThreadTerminate(cft_ThreadHandle, -1);
CloseThread(cft_ThreadHandle);if cft_count <> 0 then
if Int64(cft_count) > 0 then
finished := j;
end;
until j = 0;
i := ExtractThreadVal(finished);
j := i*UsedThreads+finished;//TestCount starts at original num
IncNumBig(num,j*stepWidth);
end;
 
i := ExtractThreadVal(finished);
j := i*UsedThreads+finished;//TestCount starts at original num
IncNumBig(num,j*stepWidth);
T1 := now;
Write(f,'Result :');
Write('Result :');
OutNumSqr;
Writeln(f,(T1 - t0) * 86400: 9: 3, ' s Testcount : ',j: 14,j*StepWidth:18);
Writeln((T1 - t0) * 86400: 9: 3, ' s Testcount : ',j: 14,j*StepWidth:18);
Writeln(UsedThreads*(T1 - t0) * 86400: 9: 3, ' s');
end;
 
var
T: TDateTime;
base: NativeUint;
begin
T := now;
Writeln(cFileName);
AssignFile(f,cFileName);
{$I-}
Append(f);
{$I+}
IF IoResult <> 0 then
rewrite(f);
gblThreadCount:= GetThreadCount;
writeln(' Cpu Count : ', gblThreadCount);
setlength(ThreadBlocks, gblThreadCount);
for base := 2 to 28 do
 
T := now;
for base := LoLimit to HiLimit do
Test(base);
Twriteln('completed :=in ', (now - T) * 86400: 0: 3, ' seconds');
writeln('completed in ', T: 0: 3, ' seconds');
writeln(f,'completed in ',T: 0: 3, ' seconds');
Close(f);
 
setlength(ThreadBlocks, 0);
{$IFDEF WINDOWS}
readln;
{$ENDIF}
end.</langsyntaxhighlight>
//{{out}}
<pre style="height:35ex">
<pre> Num 10 sqr 100
Cpu Count : 4
Base 2 test every 1
Num 10 sqr 100
Base 23 test every 1 threads = 1
Start : Num 1022 sqr 100 2101
Base 4 test every 1
Result : Num 10 sqr 100
Num 33 sqr 3201
0.000 s Testcount : 0 0
Base 5 insert 2 test every 1
Num 11 sqr 121
Num 11243 sqr 121 132304
Base 36 test every 1 threads = 15
Start : Num 11523 sqr 121 452013
Base 7 test every 6
Result : Num 11 sqr 121
Num 1431 sqr 2450361
0.000 s Testcount : 0 0
Base 8 test every 7
Num 21 sqr 1101
Num 3344 sqr 13675420
Base 4 test every 1 threads = 1
Base 9 test every 4
Start : Num 21 sqr 1101
Result : Num 3311642 sqr 3201 136802574
Base 10 test every 3
0.000 s Testcount : 6 6
Num 21432043 sqr 102411 1026753849
Base 511 test every 1 threads = 110
Start : Num 214111453 sqr 102411 1240A536789
Base 12 test every 11
Result : Num 243 sqr 132304
Num 3966B9 sqr 124A7B538609
0.000 s Testcount : 14 14
Base 13 insert 3 test every 1
Num 232 sqr 103104
Num 3828943 sqr 10254773CA86B9
Base 6 test every 5 threads = 1
Base 14 test every 13
Start : Num 235 sqr 105441
Result : Num 5233A9DB7C sqr 452013 10269B8C57D3A4
Base 15 test every 14
0.000 s Testcount : 20 100
Num 10121012B857 sqr 1024144 102597BACE836D4
Base 716 test every 6 threads = 115
Start : Num 1020404A9D9B sqr 1040400 1025648CFEA37BD9
Base 17 insert 1 test every 1
Result : Num 1431 sqr 2450361
Num 423F82GA9 sqr 101246A89CGFB357ED
0.000 s Testcount : 34 204
Base 18 test every 17
Num 2704 sqr 10237020
Num 44B482CAD sqr 10236B5F8EG4AD9CH7
Base 8 test every 7 threads = 1
Base 19 test every 6
Start : Num 2705 sqr 10244631
Result : Num 33441011B55E9A sqr 13675420 10234DHBG7CI8F6A9E5
Base 20 test every 19
0.000 s Testcount : 41 287
Num 1011749DGIH5D3G sqr 102363814 1024E7CDI3HB695FJA8G
Base 921 insert 6 test every 4 threads = 1
Num 4C9HE5FE27F sqr 1023457DG9HI8J6B6KCEAF
Start : Num 10117 sqr 102363814
Base 22 test every 21
Result : Num 11642 sqr 136802574
Num 4F94788GJ0F sqr 102369FBGDEJ48CHI7LKA5
0.000 s Testcount : 289 1156
Base 23 test every 22
Num 31992 sqr 1023488064
Num 1011D3EL56MC sqr 10234ACEDKG9HM8FBJIL756
Base 10 test every 3 threads = 1
Base 24 test every 23
Start : Num 31992 sqr 1023488064
Num 4LJ0HDGF0HD3 sqr 102345B87HFECKJNIGMDLA69
Result : Num 32043 sqr 1026753849
Base 25 test every 12
0.000 s Testcount : 17 51
Num 1011721011E145FHGHM sqr 10234761064 102345DOECKJ6GFB8LIAM7NH9
Base 1126 test every 10 threads = 15
Num 52K8N53BDM99K sqr 1023458LO6IEMKG79FPCHNJDBA
Start : Num 101175 sqr 10235267A63
Base 27 test every 26
Result : Num 111453 sqr 1240A536789
Num 1011F11E37OBJJ sqr 1023458ELOMDHBIJFGKP7CQ9N6A
0.001 s Testcount : 1498 14980
Base 28 test every 9
Num 35A924 sqr 102345A32554
Num 58A3CKP3N4CQD7 sqr 1023456CGJBIRQEDHP98KMOAN7FL
Base 12 test every 11 threads = 1
completed in 15.652 seconds
Start : Num 35A924 sqr 102345A32554
Result : Num 3966B9 sqr 124A7B538609
0.000 s Testcount : 6883 75713
Num 3824C73 sqr 10233460766739
Base 13 test every 1 threads = 1
Start : Num 3824C73 sqr 10233460766739
Result : Num 3828943 sqr 10254773CA86B9
0.000 s Testcount : 8242 8242
Num 3A9774B sqr 102345706AC8C9
Base 14 test every 13 threads = 1
Start : Num 3A9774C sqr 1023457801D984
Result : Num 3A9DB7C sqr 10269B8C57D3A4
0.000 s Testcount : 1330 17290
Num 10119106 sqr 10234567A153C26
Base 15 test every 14 threads = 1
Start : Num 10119108 sqr 1023456BA5BA144
Result : Num 1012B857 sqr 102597BACE836D4
0.000 s Testcount : 4216 59024
Num 4046641A sqr 10234567E55C52A4
Base 16 test every 15 threads = 1
Start : Num 40466424 sqr 1023456CEADC2510
Result : Num 404A9D9B sqr 1025648CFEA37BD9
0.000 s Testcount : 18457 276855
Num 423F5E486 sqr 101234567967G80FD2
Base 17 test every 1 threads = 1
Start : Num 423F5E486 sqr 101234567967G80FD2
Result : Num 423F82GA9 sqr 101246A89CGFB357ED
0.003 s Testcount : 195112 195112
Num 44B433H7D sqr 102345678F601E1FB7
Base 18 test every 17 threads = 1
Start : Num 44B433H7F sqr 102345679E6908HD69
Result : Num 44B482CAD sqr 10236B5F8EG4AD9CH7
0.001 s Testcount : 30440 517480
Num 1011B10785 sqr 102345678A30GF85556
Base 19 test every 6 threads = 1
Start : Num 1011B10789 sqr 102345678I39A8G87F5
Result : Num 1011B55E9A sqr 10234DHBG7CI8F6A9E5
0.001 s Testcount : 93021 558126
Num 49DDBE2J9C sqr 1023456789DHDH9DH834
Base 20 test every 19 threads = 12
Start : Num 49DDBE2JA0 sqr 102345678D5CCEH05000
Result : Num 49DGIH5D3G sqr 1024E7CDI3HB695FJA8G
0.021 s Testcount : 11310604 214901476
Num 4C9HE5CC2DB sqr 10234566789GK362F7BGIG
Base 21 test every 1 threads = 12
Start : Num 4C9HE5CC2DB sqr 10234566789GK362F7BGIG
Result : Num 4C9HE6GHFJF sqr 102345H7AC86GE9BKI6JDF
0.006 s Testcount : 4914193 4914193
Num 4F942523JK5 sqr 1023456789AF71694A3533
Base 22 test every 21 threads = 12
Start : Num 4F942523JL0 sqr 1023456789HL35DJ1I4100
Result : Num 4F94788GJ0F sqr 102369FBGDEJ48CHI7LKA5
0.054 s Testcount : 27804949 583903929
Num 1011D108L541 sqr 1023456789ABD6D2675E381
Base 23 test every 22 threads = 12
Start : Num 1011D108L54M sqr 1023456789C7F59L30C8ED1
Result : Num 1011D3EL56MC sqr 10234ACEDKG9HM8FBJIL756
0.038 s Testcount : 17710217 389624774
Num 4LJ0HD4763F4 sqr 1023456789ABE8FFN20B4E0G
Base 24 test every 23 threads = 12
Start : Num 4LJ0HD4763F6 sqr 1023456789AC9NJIL6HG54DC
Result : Num 4LJ0HDGF0HD3 sqr 102345B87HFECKJNIGMDLA69
0.008 s Testcount : 4266555 98130765
Num 1011E109GHMMM sqr 1023456789ABD5AHDHG370GC9
Base 25 test every 12 threads = 12
Start : Num 1011E109GHMMM sqr 1023456789ABD5AHDHG370GC9
Result : Num 1011E145FHGHM sqr 102345DOECKJ6GFB8LIAM7NH9
0.160 s Testcount : 78092125 937105500
Num 52K8N4MNP7AMA sqr 1023456789ABCMPE8HDDJL8P1M
Base 26 test every 5 threads = 12
Start : Num 52K8N4MNP7AME sqr 1023456789ABEBLL1L0F3FG7PE
Result : Num 52K8N53BDM99K sqr 1023458LO6IEMKG79FPCHNJDBA
0.884 s Testcount : 402922568 2014612840
Num 1011F10AB5HL6J sqr 1023456789ABCF787BM8395B5PA
Base 27 test every 26 threads = 12
Start : Num 1011F10AB5HL71 sqr 1023456789ABD6808CDF1LQ7AE1
Result : Num 1011F11E37OBJJ sqr 1023458ELOMDHBIJFGKP7CQ9N6A
1.049 s Testcount : 457555293 11896437618
Num 58A3CKOHN4IK4D sqr 1023456789ABCDIK29E6HB1R37Q1
Base 28 test every 9 threads = 12
Start : Num 58A3CKOHN4IK4L sqr 1023456789ABCGJDO8M4JG8HMMFL
Result : Num 58A3CKP3N4CQD7 sqr 1023456CGJBIRQEDHP98KMOAN7FL
1.672 s Testcount : 749593054 6746337486
completed in 3.898 seconds
 
real 0m15,654s
user 1m1,007s
// Ryzen 5 1600 3.4 Ghz on 6 cores/12 threads
Base 29 test every 1 threads = 12
Start : Num 5BAEFC5QHESPCLA sqr 10223456789ABCDKM4JI4S470KCSHD
Line 2,289 ⟶ 3,239:
2.00 min 1496695534873
.. 27.00 min 20178502394905
28.00 min 20925398930617 //<== > solution, because finsichfinisched tested every 1.875 seconds
Result : Num 1011J10DEFW1QTVBXR sqr 102345678RUEPV9KGQIWFOBAXCNSLDMYJHT
1681.925 s Testcount : 614575698110 20895573735740
Line 2,338 ⟶ 3,288:
 
{{libheader|ntheory}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 2,365 ⟶ 3,315:
 
say "First perfect square with N unique digits in base N: ";
say first_square($_) for 2..16;</langsyntaxhighlight>
{{out}}
<pre>First perfect square with N unique digits in base N:
Line 2,387 ⟶ 3,337:
 
{{libheader|ntheory}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use ntheory qw(:all);
Line 2,408 ⟶ 3,358:
printf("Base %2d: %10s² == %s\n", $n,
todigitstring(sqrtint($s), $n), todigitstring($s, $n));
}</langsyntaxhighlight>
 
=={{header|Phix}}==
{{libheader|Phix/mpfr}}
Partial translation of VB with bitmap idea from C++ and adopting the digit-array approach from pascal
instead of base conversion.
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>-- demo\rosetta\PandigitalSquares.exw
<span style="color: #000080;font-style:italic;">-- demo\rosetta\PandigitalSquares.exw</span>
include mpfr.e
<span style="color: #008080;">without</span> <span style="color: #008080;">javascript_semantics</span> <span style="color: #000080;font-style:italic;">-- (mpz_set_str() currently only supports bases 2, 8, 10, and 16 under pwa/p2js)</span>
atom t0 = time()
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
constant chars = "0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz|",
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
use_hll_code = true
<span style="color: #008080;">constant</span> <span style="color: #000000;">chars</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz|"</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">use_hll_code</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
function str_conv(sequence s, integer mode=+1)
-- mode of +1: eg {1,2,3} -> "123", mode of -1 the reverse.
<span style="color: #008080;">function</span> <span style="color: #000000;">str_conv</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">=+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
-- note this doesn't really care what base s/res are in.
<span style="color: #000080;font-style:italic;">-- mode of +1: eg {1,2,3} -&gt; "123", mode of -1 the reverse.
{sequence res,integer dcheck} = iff(mode=+1?{"",9}:{{},'9'})
-- note this doesn't really care what base s/res are in.</span>
for i=1 to length(s) do
<span style="color: #0000FF;">{</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #004080;">integer</span> <span style="color: #000000;">dcheck</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mode</span><span style="color: #0000FF;">=+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">}:{{},</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">})</span>
integer d = s[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
d += mode*iff(d>dcheck?'a'-10:'0')
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
res &= d
<span style="color: #000000;">d</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">*</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">></span><span style="color: #000000;">dcheck</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">d</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure do_one(integer base)
-- tabulates one base
<span style="color: #008080;">procedure</span> <span style="color: #000000;">do_one</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
integer bm1 = base-1,
<span style="color: #000080;font-style:italic;">-- tabulates one base</span>
dr = iff(and_bits(base,1) ? floor(base/2) : 0),
<span style="color: #004080;">integer</span> <span style="color: #000000;">bm1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
id = 0,
<span style="color: #000000;">dr</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">base</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">base</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">),</span>
rc = 0,
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
sdri
<span style="color: #000000;">rc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
atom st = time()
<span style="color: #000000;">sdri</span>
sequence sdr = repeat(0,bm1)
<span style="color: #004080;">atom</span> <span style="color: #000000;">st</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
for i=0 to bm1-1 do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sdr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bm1</span><span style="color: #0000FF;">)</span>
sdri = mod(i*i,bm1)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">bm1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
rc += (sdri==dr)
<span style="color: #000000;">sdri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bm1</span><span style="color: #0000FF;">)</span>
sdr[i+1] = iff(sdri=0 ? bm1 : sdri)
<span style="color: #000000;">rc</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">sdri</span><span style="color: #0000FF;">==</span><span style="color: #000000;">dr</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000000;">sdr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sdri</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #0000FF;">?</span> <span style="color: #000000;">bm1</span> <span style="color: #0000FF;">:</span> <span style="color: #000000;">sdri</span><span style="color: #0000FF;">)</span>
if dr>0 then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
id = base
<span style="color: #008080;">if</span> <span style="color: #000000;">dr</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
for i=1 to dr do
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base</span>
sdri = sdr[i+1]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">dr</span> <span style="color: #008080;">do</span>
if sdri>=dr
<span style="color: #000000;">sdri</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sdr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
and id>sdri then
<span style="color: #008080;">if</span> <span style="color: #000000;">sdri</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">dr</span>
id = sdri
<span style="color: #008080;">and</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">></span><span style="color: #000000;">sdri</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sdri</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
id -= dr
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end if
<span style="color: #000000;">id</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">dr</span>
string sq = chars[1..base]
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if id>0 then sq = sq[1..id]&chars[id+1]&sq[id+1..$] end if
<span style="color: #004080;">string</span> <span style="color: #000000;">sq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">chars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">base</span><span style="color: #0000FF;">]</span>
sq[1..2] = "10"
<span style="color: #008080;">if</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">sq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">chars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">sq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
mpz sqz = mpz_init(),
<span style="color: #000000;">sq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"10"</span>
rtz = mpz_init(),
<span style="color: #004080;">mpz</span> <span style="color: #000000;">sqz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
dnz = mpz_init(),
<span style="color: #000000;">rtz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
tmp = mpz_init()
<span style="color: #000000;">dnz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
mpz_set_str(sqz,sq,base)
<span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
mpz_sqrt(rtz,sqz)
<span style="color: #7060A8;">mpz_set_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sq</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
mpz_add_ui(rtz,rtz,1) -- rtz = sqrt(sqz)+1
<span style="color: #7060A8;">mpz_sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">)</span>
mpz_mul_si(dnz,rtz,2)
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- rtz = sqrt(sqz)+1</span>
mpz_add_si(dnz,dnz,1) -- dnz = rtz*2+1
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
mpz_mul(sqz,rtz,rtz) -- sqz = rtz * rtz
<span style="color: #7060A8;">mpz_add_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- dnz = rtz*2+1</span>
integer d = 1,
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- sqz = rtz * rtz</span>
inc = 1
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
if base>3 and rc>0 then
<span style="color: #000000;">inc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
while mpz_fdiv_ui(sqz,bm1)!=dr do
<span style="color: #008080;">if</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">></span><span style="color: #000000;">3</span> <span style="color: #008080;">and</span> <span style="color: #000000;">rc</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
-- align sqz to dr
<span style="color: #008080;">while</span> <span style="color: #7060A8;">mpz_fdiv_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bm1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">dr</span> <span style="color: #008080;">do</span>
mpz_add_ui(rtz,rtz,1) -- rtz += 1
mpz_add(sqz,sqz,dnz) <span style="color: #000080;font-style:italic;">-- align sqz +=to dnzdr</span>
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- rtz += 1</span>
mpz_add_ui(dnz,dnz,2) -- dnz += 2
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- sqz += dnz</span>
end while
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- dnz += 2</span>
inc = floor(bm1/rc)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if inc>1 then
<span style="color: #000000;">inc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bm1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">rc</span><span style="color: #0000FF;">)</span>
mpz_mul_si(tmp,rtz,inc-2)
<span style="color: #008080;">if</span> <span style="color: #000000;">inc</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
mpz_sub_ui(tmp,tmp,1)
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
mpz_add(dnz,dnz,tmp) -- dnz += rtz*(inc-2)-1
<span style="color: #7060A8;">mpz_sub_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- dnz += rtz*(inc-2)-1</span>
d = inc * inc
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
mpz_add(dnz,dnz,dnz)
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">inc</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">inc</span>
mpz_add_ui(dnz,dnz,d) -- dnz += dnz + d
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- dnz += dnz + d</span>
d *= 2
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
atom mask, fullmask = power(2,base)-1 -- ie 0b111..
<span style="color: #000000;">d</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">2</span>
integer icount = 0
<span style="color: #004080;">atom</span> <span style="color: #000000;">mask</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fullmask</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- ie 0b111..</span>
mpz_set_si(tmp,d)
<span style="color: #004080;">integer</span> <span style="color: #000000;">icount</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
sequence sqi = str_conv(mpz_get_str(sqz,base), mode:=-1),
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
dni = str_conv(mpz_get_str(dnz,base), mode:=-1),
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sqi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str_conv</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">:=-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
dti = str_conv(mpz_get_str(tmp,base), mode:=-1)
<span style="color: #000000;">dni</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str_conv</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">:=-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
while true do
<span style="color: #000000;">dti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str_conv</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">:=-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
if use_hll_code then
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
mask = 0
<span style="color: #008080;">if</span> <span style="color: #000000;">use_hll_code</span> <span style="color: #008080;">then</span>
for i=1 to length(sqi) do
<span style="color: #000000;">mask</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
mask = or_bits(mask,power(2,sqi[i]))
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqi</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">mask</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">or_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mask</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sqi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]))</span>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
?9/0 -- see below, inline part 1
<span style="color: #008080;">else</span>
end if
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- see below, inline part 1</span>
if mask=fullmask then exit end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer carry = 0, sidx, si
<span style="color: #008080;">if</span> <span style="color: #000000;">mask</span><span style="color: #0000FF;">=</span><span style="color: #000000;">fullmask</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if use_hll_code then
<span style="color: #004080;">integer</span> <span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sidx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">si</span>
for sidx=-1 to -length(dni) by -1 do
<span style="color: #008080;">if</span> <span style="color: #000000;">use_hll_code</span> <span style="color: #008080;">then</span>
si = sqi[sidx]+dni[sidx]+carry
<span style="color: #008080;">for</span> <span style="color: #000000;">sidx</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dni</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
carry = si>=base
<span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sqi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">dni</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">carry</span>
sqi[sidx] = si-carry*base
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">base</span>
end for
<span style="color: #000000;">sqi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">-</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base</span>
sidx += length(sqi)+1
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
while carry and sidx do
<span style="color: #000000;">sidx</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqi</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
si = sqi[sidx]+carry
<span style="color: #008080;">while</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">and</span> <span style="color: #000000;">sidx</span> <span style="color: #008080;">do</span>
carry = si>=base
<span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sqi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">carry</span>
sqi[sidx] = si-carry*base
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">base</span>
sidx -= 1
<span style="color: #000000;">sqi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">-</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base</span>
end while
<span style="color: #000000;">sidx</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
?9/0 --see below, inline part 2
<span style="color: #008080;">else</span>
end if
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">--see below, inline part 2</span>
if carry then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sqi = carry&sqi
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">sqi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">carry</span><span style="color: #0000FF;">&</span><span style="color: #000000;">sqi</span>
carry = 0
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for sidx=-1 to -length(dti) by -1 do
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
si = dni[sidx]+dti[sidx]+carry
<span style="color: #008080;">for</span> <span style="color: #000000;">sidx</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dti</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
carry = floor(si/base)
<span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dni</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">dti</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">carry</span>
dni[sidx] = remainder(si,base)
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">si</span><span style="color: #0000FF;">/</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000000;">dni</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">si</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
sidx += length(dni)+1
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
while carry and sidx do
<span style="color: #000000;">sidx</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dni</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
si = dni[sidx]+carry
<span style="color: #008080;">while</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">and</span> <span style="color: #000000;">sidx</span> <span style="color: #008080;">do</span>
carry = si>=base
<span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dni</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">carry</span>
dni[sidx] = si-carry*base
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">base</span>
sidx -= 1
<span style="color: #000000;">dni</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">si</span><span style="color: #0000FF;">-</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base</span>
end while
<span style="color: #000000;">sidx</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
if carry then
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
dni = carry&dni
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">dni</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">carry</span><span style="color: #0000FF;">&</span><span style="color: #000000;">dni</span>
icount += 1
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #000000;">icount</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
mpz_set_si(tmp,icount)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
mpz_mul_si(tmp,tmp,inc)
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">icount</span><span style="color: #0000FF;">)</span>
mpz_add(rtz,rtz,tmp) -- rtz += icount * inc
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">)</span>
sq = str_conv(sqi, mode:=+1)
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- rtz += icount * inc</span>
string rt = mpz_get_str(rtz,base),
<span style="color: #000000;">sq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str_conv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sqi</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">:=+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
idstr = iff(id?sprintf("%d",id):" "),
<span style="color: #004080;">string</span> <span style="color: #000000;">rt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">),</span>
ethis = elapsed_short(time()-st),
<span style="color: #000000;">idstr</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">id</span><span style="color: #0000FF;">):</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">),</span>
etotal = elapsed_short(time()-t0)
<span style="color: #000000;">ethis</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed_short</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">st</span><span style="color: #0000FF;">),</span>
printf(1,"%3d %3d %s %18s -> %-28s %10d %8s %8s\n",
<span style="color: #000000;">etotal</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed_short</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
{base, inc, idstr, rt, sq, icount, ethis, etotal})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d %3d %s %18s -&gt; %-28s %10d %8s %8s\n"</span><span style="color: #0000FF;">,</span>
{sqz,rtz,dnz,tmp} = mpz_free({sqz,rtz,dnz,tmp})
<span style="color: #0000FF;">{</span><span style="color: #000000;">base</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">inc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">idstr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rt</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">icount</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ethis</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">etotal</span><span style="color: #0000FF;">})</span>
end procedure
<span style="color: #0000FF;">{</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_free</span><span style="color: #0000FF;">({</span><span style="color: #000000;">sqz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rtz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dnz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
puts(1,"base inc id root -> square" &
" test count time total\n")
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"base inc id root -&gt; square"</span> <span style="color: #0000FF;">&</span>
for base=2 to 19 do
<span style="color: #008000;">" test count time total\n"</span><span style="color: #0000FF;">)</span>
--for base=2 to 25 do
<span style="color: #008080;">for</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">19</span> <span style="color: #008080;">do</span>
--for base=2 to 28 do
<span style="color: #000080;font-style:italic;">--for base=2 to 25 do
do_one(base)
--for base=2 to 28 do</span>
end for
<span style="color: #000000;">do_one</span><span style="color: #0000FF;">(</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
printf(1,"completed in %s\n", {elapsed(time()-t0)})</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"completed in %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,603 ⟶ 3,556:
Requires version 0.8.1+, not yet shipped, which will include demo\rosetta\PandigitalSquares.exw<br>
64 bit code omitted for clarity, the code in PandigitalSquares.exw is twice as long.
<langsyntaxhighlight Phixlang="phix">-- ?9/0 -- see below, inline part 1
mask = length(sqi)
#ilASM{
Line 2,661 ⟶ 3,614:
@@:
mov [carry],eax
}</langsyntaxhighlight>
{{output}}
<pre>
Line 2,676 ⟶ 3,629:
=={{header|Python}}==
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Perfect squares using every digit in a given base.'''
 
from itertools import (count, dropwhile, repeat)
from math import (ceil, sqrt)
from time import time
 
Line 2,689 ⟶ 3,642:
'''
bools = list(repeat(True, base))
return next(dropwhile(missingDigitsAtBase(base, bools), count(
dropwhile(
max(above, ceil(sqrt(int('10' + '0123456789abcdef'[2:base], base))))
missingDigitsAtBase(base, bools),
)))
count(
max(
above,
ceil(sqrt(int(
'10' + '0123456789abcdef'[2:base],
base
)))
)
)
)
)
 
 
# missingDigitsAtBase :: Int -> [Bool] -> Int -> Bool
def missingDigitsAtBase(base, bools):
'''Fusion of representing the square of integer N at a given base
given base with checking whether all digits of that base contribute to N^2.
that base contribute to N^2.
Clears the bool at a digit position to False when used.
True if any positions remain uncleared (unused).
Line 2,716 ⟶ 3,681:
 
 
# TEST --------------------------- TEST -------------------------
# main :: IO ()
def main():
Line 2,729 ⟶ 3,694:
print(
str(b).rjust(2, ' ') + ' -> ' +
showIntAtBase(b)(digit)(q)('').rjust(8, ' ') + ' -> ' +
' -> ' +
showIntAtBase(b)(digit)(q * q)('')
)
Line 2,738 ⟶ 3,704:
 
 
# GENERIC ------------------------- GENERIC ------------------------
 
# enumFromTo :: (Int, Int) -> [Int]
Line 2,746 ⟶ 3,712:
 
 
# showIntAtBase :: Int -> (Int -> String) -> Int -> String -> String
# String -> String
def showIntAtBase(base):
'''String representation of an integer in a given base,
Line 2,768 ⟶ 3,735:
# MAIN ---
if __name__ == '__main__':
main()</lang>
</syntaxhighlight>
{{Out}}
<pre>Smallest perfect squares using all digits in bases 2-16:
Line 2,790 ⟶ 3,758:
 
c. 30 seconds.</pre>
 
=={{header|Quackery}}==
 
<code>from</code>, <code>index</code>, and <code>end</code> are defined at [[Loops/Increment loop index within loop body#Quackery]].
 
<syntaxhighlight lang="Quackery"> [ dup 1
[ 2dup > while
+ 1 >>
2dup / again ]
drop nip ] is sqrt ( n --> n )
 
[ base share bit 1 -
0 rot
[ dup while
base share /mod bit
rot | swap again ]
drop = ] is pandigital ( n --> b )
 
[ base share
dup 2 - times
[ base share *
i^ 2 + + ] ] is firstpan ( --> n )
 
[ dup * ] is squared ( n --> n )
 
11 times
[ i^ 2 + base put
firstpan sqrt from
[ index squared
pandigital if
[ index end ] ]
base share
say "Base " decimal echo
base release
say ": " dup echo
say "^" 2 echo say " = "
squared echo
cr base release ]</syntaxhighlight>
 
{{out}}
 
<pre>Base 2: 10^10 = 100
Base 3: 22^2 = 2101
Base 4: 33^2 = 3201
Base 5: 243^2 = 132304
Base 6: 523^2 = 452013
Base 7: 1431^2 = 2450361
Base 8: 3344^2 = 13675420
Base 9: 11642^2 = 136802574
Base 10: 32043^2 = 1026753849
Base 11: 111453^2 = 1240A536789
Base 12: 3966B9^2 = 124A7B538609</pre>
 
=={{header|Raku}}==
Line 2,804 ⟶ 3,824:
[https://tio.run/##dVTNbtpAEL7zFBPXBDuBlQ1SqkDz0x4i5VBeoGqQA@uwlVmb3XVThMi5fZ1ce@NR@iJ0Zm1jO1UtYS8zO9/8fDOTcZVcHA65FAZ0/gifP95PwXONWHEFV3AXJZr7k06HdLFQ2gz0Oo8UB@9eGnClD9sO4LPawK02kTJoFCeRgV7Y60MvwJc3BMYe6O7@N3uMNB/jGSHJTMR4hmsIA9jCO4hklGyMmGurLHFdlaYGEHchnoSJkgH990p37FsqZB/GhOtROBhsw/aW7mq09YaMoZqtosw727/awxh9tjDdGatwWpCwq0EpYhvQn5@/KvjtUVuFnMax5lSLlZBecYs9KY4uzzDbAsCHQXGatMyLvL6E5yXIV0Sp8F7@1dbGu07xrvhwKz4alWJZpDQfVKkxvUbFnItEyKfJkUhbFKqa4t853gfv4S17Rx/r@izTZ6IJP7WMGgllQcNCFec4VVWIjGFZ6iIiKJqw/WuLSpcCQtWRorY2rv@6Md4MsZkWkETaQC4TrjXasnkqTSSkxhxmNoAy1Ta9RfOfnpateWmPM@h2IZwFQUC/N5QXaZ7b3InVYwmqR0cbcKaoGANs3dlu/1okAx9cfQ3YiF5t6TOV5nLhsSAI/Z124KUFRY9DJtZp6y7wJMo0Xzht55aYBi91s9Aj@Q9j025WUNPwu7NaQoXs1IY6U0Ka2APnE7IB3eFiDN1wpCmvK@gORoF2@ui4T1CNoWryhwNQZ1atnJub8gjn8J@SwMkJ9HpI/65YS80RRmP7ERrmabbBKXbJHfVDUK2q4sZV8cWWWD3arbAdjy5wA/g7nIp8VUZJbx@elyLh1f0lThC1xaQGa02VNSmCQ9LBuaOtCRlXMZ/jji2257MwS5hiZ4p1zqGcNyHBBjsdAzJI1uy0tXOpY2m5kmdaqhAO@7g1FV/nQvEFisORFV@QOM2MSHGhkvi9FV@SWBvFzXzZmRwOfwE Try it online!]
 
<syntaxhighlight lang="raku" perl6line>#`[
 
Only search square numbers that have at least N digits;
Line 2,869 ⟶ 3,889:
25, # very slow
26, # "
;</langsyntaxhighlight>
{{out}}
<pre>First perfect square with N unique digits in base N:
Line 2,906 ⟶ 3,926:
These REXX versions can handle up to base '''36''', but could be extended.
===slightly optimized===
<langsyntaxhighlight lang="rexx">/*REXX program finds/displays the first perfect square with N unique digits in base N.*/
numeric digits 40 /*ensure enough decimal digits for a #.*/
parse arg nLO HI . /*obtain optional argument from the CL.*/
if nLO=='' | n=="," then n= 16 then do; LO=2; HI=16; end /*not specified? Then use the default.*/
if LO==',' then LO=2 /*not specified? Then use the default.*/
if HI=='' | HI=="," then HI=LO /*not specified? Then use the default.*/
@start= 1023456789abcdefghijklmnopqrstuvwxyz /*contains the start # (up to base 36).*/
w= length(n) /* [↓] find the smallest square with */
do j=2LO to nHI; beg= left(@start, j) /* N unique digits in base N. */
do k=iSqrt( base(beg,10,j) ) until #==0 /*start each search from smallest sqrt.*/
$= base(k*k, j, 10) /*calculate square, convert to base J. */
Line 2,918 ⟶ 3,940:
#= verify(beg, $u) /*count differences between 2 numbers. */
end /*k*/
say 'base' right(j,w) " root=" right(base(k,j,10),max length(5,nHI) ) ' square " root='" $,
lower( right( base(k, j, 10), max(5, HI) ) ) ' square=' lower($)
end /*j*/
exit /*stick a fork in it, we're all done. */
Line 2,926 ⟶ 3,949:
@u= @l; upper @u /*uppercase " " " " */
if inb\==10 then /*only convert if not base 10. */
do 1; #= 0 /*result of converted X (in base 10).*/
if inb==2 then do; #= b2d(x); leave; end /*convert binary to decimal. */
if inb==16 then do; #= x2d(x); leave; end /* " hexadecimal " " */
do j=1 for length(x) /*convert X: base inB ──► base 10. */
#= # * inB + pos(substr(x,j,1), @u)-1 /*build a new number, digit by digit. */
Line 2,933 ⟶ 3,958:
y= /*the value of X in base B (so far).*/
if tob==10 then return # /*if TOB is ten, then simply return #.*/
if tob==2 do then while return d2b(# >= toB ) /*convert #:base 10 number to basebinary. 10 ──► base toB.*/
if tob==16 then return lower( d2x(#) ) /* " " " " " hexadecimal*/
do while # >= toB /*convert #: decimal ──► base toB.*/
y= substr(@l, (# // toB) + 1, 1)y /*construct the output number. */
#= # % toB /* ··· and whittle # down also. */
Line 2,940 ⟶ 3,967:
/*──────────────────────────────────────────────────────────────────────────────────────*/
iSqrt: procedure; parse arg x; r=0; q=1; do while q<=x; q=q*4; end
do while q>1; q=q%4; _=x-r-q; r=r%2; if _>=0 then do;x=_;r=r+q; end; end; return r</lang>
/*──────────────────────────────────────────────────────────────────────────────────────*/
b2d: return x2d( b2x( arg(1) ) ) /*convert binary number to decimal*/
d2b: return x2b( d2x( arg(1) ) ) + 0 /* " hexadecimal " " " */
lower: @abc= 'abcdefghijklmnopqrstuvwxyz'; return translate(arg(1), @abc, translate(@abc))</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
base 2 root= 10 square= 100
base 3 root= 22 square= 2101
base 4 root= 33 square= 3201
base 5 root= 243 square= 132304
base 6 root= 523 square= 452013
base 7 root= 1431 square= 2450361
base 8 root= 3344 square= 13675420
base 9 root= 11642 square= 136802574
base 10 root= 32043 square= 1026753849
base 11 root= 111453 square= 1240a536789
base 12 root= 3966b9 square= 124a7b538609
base 13 root= 3828943 square= 10254773ca86b9
base 14 root= 3a9db7c square= 10269b8c57d3a4
base 15 root= 1012b857 square= 102597bace836d4
base 16 root= 404a9d9b square= 1025648cfea37bd9
</pre>
 
Line 2,964 ⟶ 3,995:
 
It is about &nbsp; '''10%''' &nbsp; faster.
<langsyntaxhighlight lang="rexx">/*REXX program finds/displays the first perfect square with N unique digits in base N.*/
numeric digits 40 /*ensure enough decimal digits for a #.*/
parse arg nLO HI . /*obtain optional argument from the CL.*/
if nLO=='' | n=="," then n= 16 then do; LO=2; HI=16; end /*not specified? Then use the default.*/
if LO==',' then LO=2 /* " " " " " " */
if HI=='' | HI=="," then HI=LO /* " " " " " " */
@start= 1023456789abcdefghijklmnopqrstuvwxyz /*contains the start # (up to base 36).*/
call base /*initialize 2 arrays for BASE function*/
/* [↓] find the smallest square with */
do j=2LO to nHI; beg= left(@start, j) /* N unique digits in base N. */
do k=iSqrt( base(beg,10,j) ) until #==0 /*start each search from smallest sqrt.*/
$= base(k*k, j, 10) /*calculate square, convert to base J. */
#= verify(beg, $) /*count differences between 2 numbers. */
end /*k*/
say 'base' right(j, length(nHI) ) " root=" ,
lower( right( base(k, j, 10), max(5, nHI) ) ) ' square=' lower($)
end /*j*/
exit /*stick a fork in it, we're all done. */
Line 2,988 ⟶ 4,021:
end /*i*/ /* [↑] assign shortcut radix values. */
if inb\==10 then /*only convert if not base 10. */
do 1; #= 0 /*result of converted X (in base 10).*/
if inb==2 then do; #= b2d(x); leave; end /*convert binary to decimal. */
if inb==16 then do; #= x2d(x); leave; end /* " hexadecimal " " */
do j=1 for length(x) /*convert X: base inB ──► base 10. */
_= substr(x, j, 1); #= # * inB + !._ /*build a new number, digit by digit. */
Line 2,995 ⟶ 4,030:
y= /*the value of X in base B (so far).*/
if tob==10 then return # /*if TOB is ten, then simply return #.*/
if tob==2 then return d2b(#) /*convert base 10 number to binary. */
if tob==16 then return d2x(#) /* " " " " " hexadecimal*/
do while # >= toB /*convert #: base 10 ──► base toB.*/
_= # // toB; y= !!._ || y /*construct the output number. */
Line 3,004 ⟶ 4,041:
do while q>1; q=q%4; _=x-r-q; r=r%2; if _>=0 then do;x=_;r=r+q; end; end; return r
/*──────────────────────────────────────────────────────────────────────────────────────*/
b2d: return x2d( b2x( arg(1) ) ) /*convert binary number to decimal*/
lower: @abc= 'abcdefghijklmnopqrstuvwxyz'; return translate(arg(1), @abc, translate(@abc))</lang>
d2b: return x2b( d2x( arg(1) ) ) + 0 /* " hexadecimal " " " */
lower: @abc= 'abcdefghijklmnopqrstuvwxyz'; return translate(arg(1), @abc, translate(@abc))</syntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}} <br><br>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
basePlus = []
decList = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
baseList = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]
 
see "working..." + nl
 
for base = 2 to 10
for n = 1 to 40000
basePlus = []
nrPow = pow(n,2)
str = decimaltobase(nrPow,base)
ln = len(str)
for m = 1 to ln
nr = str[m]
ind = find(baseList,nr)
num = decList[ind]
add(basePlus,num)
next
flag = 1
basePlus = sort(basePlus)
if len(basePlus) = base
for p = 1 to base
if basePlus[p] = p-1
flag = 1
else
flag = 0
exit
ok
next
if flag = 1
see "in base: " + base + " root: " + n + " square: " + nrPow + " perfect square: " + str + nl
exit
ok
ok
next
next
see "done..." + nl
 
func decimaltobase(nr,base)
binList = []
binary = 0
remainder = 1
while(nr != 0)
remainder = nr % base
ind = find(decList,remainder)
rem = baseList[ind]
add(binList,rem)
nr = floor(nr/base)
end
binlist = reverse(binList)
binList = list2str(binList)
binList = substr(binList,nl,"")
return binList
</syntaxhighlight>
{{out}}
<pre>
in base: 4 root: 15 square: 225 perfect square: 3201
in base: 6 root: 195 square: 38025 perfect square: 452013
in base: 7 root: 561 square: 314721 perfect square: 2450361
in base: 8 root: 1764 square: 3111696 perfect square: 13675420
in base: 9 root: 7814 square: 61058596 perfect square: 136802574
in base: 10 root: 32043 square: 1026753849 perfect square: 1026753849
done...
</pre>
 
=={{header|RPL}}==
{{works with|HP|49}}
≪ → base
≪ { } base + 0 CON SWAP
'''WHILE''' DUP '''REPEAT'''
base IDIV2
ROT SWAP 1 + DUP PUT SWAP
'''END'''
DROP OBJ→ 1 GET →LIST ΠLIST
≫ ≫ '<span style="color:blue">PANB?</span>' STO <span style="color:grey">@ ''( number base → boolean )''</span>
≪ → base
≪ ""
'''WHILE''' OVER '''REPEAT'''
SWAP base IDIV2
"0123456789ABCDEF" SWAP 1 + DUP SUB
ROT +
'''END'''
SWAP DROP
≫ ≫ '<span style="color:blue">→B</span>' STO <span style="color:grey">@ ''( number_10 base → "number_base" )''</span>
≪ → base
≪ 0
1 base 1 - '''FOR''' j <span style="color:grey">@ this loop generates the smallest pandigital number for the base</span>
base
'''IF''' j 2 == '''THEN''' SQ '''END'''
* j +
'''NEXT'''
√ IP
'''WHILE''' DUP SQ base <span style="color:blue">PANB?</span> NOT '''REPEAT''' 1 + '''END'''
base ": " +
OVER base <span style="color:blue">→B</span> + "² = " +
SWAP SQ base <span style="color:blue">→B</span> +
≫ ≫ ‘<span style="color:blue">SQPAN</span>’ STO <span style="color:grey">@ ''( → "base: n² = pandigital" )''</span>
≪ { }
2 15 '''FOR''' b
base <span style="color:blue">SQPAN</span> + '''NEXT'''
≫ ‘<span style="color:blue">TASK</span>’ STO
The above code can be run on a HP-48G if <code>IDIV2</code> is implemented such as : <code>≪ MOD LASTARG / IP SWAP ≫</code>
{{out}}
<pre>
1: { "2: 10² = 100" "3: 22² = 2101" "4: 33² = 3201" "5: 243² = 132304" "6: 523² = 452013" "7: 1431² = 2450361"
"8: 3344² = 13675420" "9: 11642² = 136802574" "10: 32043² = 1026753849" "11: 111453² = 1240A536789" "12: 3966B9² = 124A7B538609" "13: 3828943² = 10254773CA86B9" "14: 3A9DB7C² = 10269B8C57D3A4" "15: 1012B857² = 102597BACE836D4" }
</pre>
 
=={{header|Ruby}}==
Takes about 15 seconds on my dated PC, most are spent calculating base 13.
<langsyntaxhighlight lang="ruby">DIGITS = "1023456789abcdefghijklmnopqrstuvwxyz"
 
2.upto(16) do |n|
Line 3,016 ⟶ 4,168:
puts "Base %2d:%10s² = %-14s" % [n, res.to_s(n), (res*res).to_s(n)]
end
</syntaxhighlight>
</lang>
{{out}}
<pre>Base 2: 10² = 100
Line 3,036 ⟶ 4,188:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func first_square(b) {
 
var start = [1, 0, (2..^b)...].flip.map_kv{|k,v| v * b**k }.sum.isqrt
Line 3,048 ⟶ 4,200:
var s = first_square(b)
printf("Base %2d: %10s² == %s\n", b, s.isqrt.base(b), s.base(b))
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,068 ⟶ 4,220:
</pre>
 
=={{header|Uiua}}==
No integer arithmetic in Uiua, so it's a bit slow...
<syntaxhighlight lang="Uiua">
BaseN ← setinv(↘2⍢(⊂⊂:⊙(⊃(↙1)(↘2))⊂⊃(⌊÷)◿°⊟↙2.)(>0 ⊢↘1)⊟|/+×ⁿ:⊙(⇌⇡⧻.))
IsPan ← =⧻◴: # IsPan 3 [0 1 2]
# Smallest pan number for given base
# = [1 0 2 3 4...] in base n
MinPanBase ← °BaseN ⟜(↙:⊂[1 0]↘2⇡+1.)
MinPanSqrBase ← ⊙◌⍢(+1)(¬IsPan :BaseN ,×.) ⌊√MinPanBase.
ShowMinPan ← (
≡(
&pf "\t" &pf . &pf "Base "
MinPanSqrBase .
&p BaseN : &pf "\t" &pf. × &pf "\t" &pf. .
)
)
 
⍜now (ShowMinPan ↘2⇡13)
</syntaxhighlight>
 
{{out}}
<pre>
stdout:
Base 2 2 4 [1 0 0]
Base 3 8 64 [2 1 0 1]
Base 4 15 225 [3 2 0 1]
Base 5 73 5329 [1 3 2 3 0 4]
Base 6 195 38025 [4 5 2 0 1 3]
Base 7 561 314721 [2 4 5 0 3 6 1]
Base 8 1764 3111696 [1 3 6 7 5 4 2 0]
Base 9 7814 61058596 [1 3 6 8 0 2 5 7 4]
Base 10 32043 1026753849 [1 0 2 6 7 5 3 8 4 9]
Base 11 177565 31529329225 [1 2 4 0 10 5 3 6 7 8 9]
Base 12 944493 892067027049 [1 2 4 10 7 11 5 3 8 6 0 9]
 
17.243999999999915 [ooof]
</pre>
=={{header|Visual Basic .NET}}==
{{libheader|System.Numerics}}
This is faster than the Go version, but not as fast as the Pascal version. The Pascal version uses an array of integers to represent the square, as it's more efficient to increment and check that way.<br/>This Visual Basic .NET version uses BigInteger variables for computation. It's quick enough for up to base19, tho.<langsyntaxhighlight lang="vbnet">Imports System.Numerics
 
Module Program
Line 3,144 ⟶ 4,333:
Console.WriteLine("Elasped time was {0,8:0.00} minutes", (DateTime.Now - st0).TotalMinutes)
End Sub
End Module</langsyntaxhighlight>
{{out}}This output is on a somewhat modern PC. For comparison, it takes TIO.run around 30 seconds to reach base20, so TIO.run is around 3 times slower there.
<pre>base inc id root square test count time total
Line 3,175 ⟶ 4,364:
28 9 58A3CKP3N4CQD7 -> 1023456CGJBIRQEDHP98KMOAN7FL 749593055 711.660s 1617.981s
Elasped time was 26.97 minutes</pre>Base29 seems to take an order of magnitude longer. I'm looking into some shortcuts.
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-big}}
{{libheader|Wren-math}}
{{libheader|Wren-fmt}}
Base 21 is as far as we can reasonably fly here though (unsurprisingly) base 20 takes a long time.
<syntaxhighlight lang="wren">import "./big" for BigInt
import "./math" for Nums
import "./fmt" for Conv, Fmt
 
var maxBase = 21
var minSq36 = "1023456789abcdefghijklmnopqrstuvwxyz"
var minSq36x = "10123456789abcdefghijklmnopqrstuvwxyz"
 
var containsAll = Fn.new { |sq, base|
var found = List.filled(maxBase, 0)
var le = sq.count
var reps = 0
for (r in sq) {
var d = r.bytes[0] - 48
if (d > 38) d = d - 39
found[d] = found[d] + 1
if (found[d] > 1) {
reps = reps + 1
if (le - reps < base) return false
}
}
return true
}
 
var sumDigits = Fn.new { |n, base|
var sum = BigInt.zero
while (n > 0) {
sum = sum + (n%base)
n = n/base
}
return sum
}
 
var digitalRoot = Fn.new { |n, base|
while (n > base - 1) n = sumDigits.call(n, base)
return n.toSmall
}
 
var minStart = Fn.new { |base|
var ms = minSq36[0...base]
var nn = BigInt.fromBaseString(ms, base)
var bdr = digitalRoot.call(nn, base)
var drs = []
var ixs = []
for (n in 1...2*base) {
nn = BigInt.new(n*n)
var dr = digitalRoot.call(nn, base)
if (dr == 0) dr = n * n
if (dr == bdr) ixs.add(n)
if (n < base && dr >= bdr) drs.add(dr)
}
var inc = 1
if (ixs.count >= 2 && base != 3) inc = ixs[1] - ixs[0]
if (drs.count == 0) return [ms, inc, bdr]
var min = Nums.min(drs)
var rd = min - bdr
if (rd == 0) return [ms, inc, bdr]
if (rd == 1) return [minSq36x[0..base], 1, bdr]
var ins = minSq36[rd]
return [(minSq36[0...rd] + ins + minSq36[rd..-1])[0..base], inc, bdr]
}
 
var start = System.clock
var n = 2
var k = 1
var base = 2
while (true) {
if (base == 2 || (n % base) != 0) {
var nb = BigInt.new(n)
var sq = nb.square.toBaseString(base)
if (containsAll.call(sq, base)) {
var ns = Conv.itoa(n, base)
var tt = System.clock - start
Fmt.print("Base $2d:$15s² = $-27s in $8.3fs", base, ns, sq, tt)
if (base == maxBase) break
base = base + 1
var res = minStart.call(base)
var ms = res[0]
var inc = res[1]
var bdr = res[2]
k = inc
var nn = BigInt.fromBaseString(ms, base)
nb = nn.isqrt
if (nb < n + 1) nb = BigInt.new(n+1)
if (k != 1) {
while (true) {
nn = nb.square
var dr = digitalRoot.call(nn, base)
if (dr == bdr) {
n = nb.toSmall - k
break
}
nb = nb.inc
}
} else {
n = nb.toSmall - k
}
}
}
n = n + k
}</syntaxhighlight>
 
{{out}}
<pre>
Base 2: 10² = 100 in 0.000s
Base 3: 22² = 2101 in 0.000s
Base 4: 33² = 3201 in 0.001s
Base 5: 243² = 132304 in 0.001s
Base 6: 523² = 452013 in 0.002s
Base 7: 1431² = 2450361 in 0.003s
Base 8: 3344² = 13675420 in 0.004s
Base 9: 11642² = 136802574 in 0.011s
Base 10: 32043² = 1026753849 in 0.011s
Base 11: 111453² = 1240a536789 in 0.044s
Base 12: 3966b9² = 124a7b538609 in 0.201s
Base 13: 3828943² = 10254773ca86b9 in 0.426s
Base 14: 3a9db7c² = 10269b8c57d3a4 in 0.501s
Base 15: 1012b857² = 102597bace836d4 in 0.651s
Base 16: 404a9d9b² = 1025648cfea37bd9 in 1.351s
Base 17: 423f82ga9² = 101246a89cgfb357ed in 10.534s
Base 18: 44b482cad² = 10236b5f8eg4ad9ch7 in 12.008s
Base 19: 1011b55e9a² = 10234dhbg7ci8f6a9e5 in 18.055s
Base 20: 49dgih5d3g² = 1024e7cdi3hb695fja8g in 696.567s
Base 21: 4c9he5fe27f² = 1023457dg9hi8j6b6kceaf in 735.738s
</pre>
 
=={{header|XPL0}}==
Base 14 is the largest that can be calculated using double precision
floating point (14^13 = 7.9e14; 15^14 = 2.9e16). Runs in about 38 seconds
on Pi4.
<syntaxhighlight lang "XPL0">real Base; \Number Base used [2..14]
 
proc NumOut(N); \Display N in the specified Base
real N;
int Remain;
[Remain:= fix(Mod(N, Base));
N:= Floor(N/Base);
if N # 0. then NumOut(N);
ChOut(0, Remain + (if Remain <= 9 then ^0 else ^A-10));
];
 
func Pandigital(N); \Return 'true' if N is pandigital
real N;
int Used, Remain;
[Used:= 0;
while N # 0. do
[Remain:= fix(Mod(N, Base));
N:= Floor(N/Base);
Used:= Used ! 1<<Remain;
];
return Used = 1<<fix(Base) - 1;
];
 
real N;
[Base:= 2.;
Format(2, 0);
repeat N:= Floor(Sqrt(Pow(Base, Base-1.)));
loop [if Pandigital(N*N) then
[RlOut(0, Base); Text(0, ": ");
NumOut(N); Text(0, "^^2 = ");
NumOut(N*N); CrLf(0);
quit;
];
N:= N + 1.;
];
Base:= Base + 1.;
until Base > 14.;
]</syntaxhighlight>
{{out}}
<pre>
2: 10^2 = 100
3: 22^2 = 2101
4: 33^2 = 3201
5: 243^2 = 132304
6: 523^2 = 452013
7: 1431^2 = 2450361
8: 3344^2 = 13675420
9: 11642^2 = 136802574
10: 32043^2 = 1026753849
11: 111453^2 = 1240A536789
12: 3966B9^2 = 124A7B538609
13: 3828943^2 = 10254773CA86B9
14: 3A9DB7C^2 = 10269B8C57D3A4
</pre>
 
=={{header|zkl}}==
{{trans|Julia}}
<langsyntaxhighlight lang="zkl">fcn squareSearch(B){
basenumerals:=B.pump(String,T("toString",B)); // 13 --> "0123456789abc"
highest:=("10"+basenumerals[2,*]).toInt(B); // 13 --> "10" "23456789abc"
Line 3,186 ⟶ 4,566:
}
Void
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">println("Base Root N");
foreach b in ([2..16])
{ println("%2d %10s %s".fmt(b,squareSearch(b).xplode())) }</langsyntaxhighlight>
{{out}}
<pre>
2,021

edits