Jordan-Pólya numbers: Difference between revisions
Content added Content deleted
(→{{header|Free Pascal}}: Convert using Uint64. misinterpretate 2^53 with 1E53 tse tse tse...) |
m (→{{header|Free Pascal}}: more comments and commatize) |
||
Line 743: | Line 743: | ||
const |
const |
||
MaxIdx = 3800;//7279 < 2^62 |
MaxIdx = 3800;//7279 < 2^62 |
||
maxFac = |
maxFac = 25;//21!> 2^63 |
||
type |
type |
||
tnum = Uint64; |
tnum = Uint64; |
||
Line 749: | Line 749: | ||
tFac_mul = packed record |
tFac_mul = packed record |
||
fm_num : tnum; |
fm_num : tnum; |
||
fm_pow : tpow; |
fm_pow : tpow; |
||
fm_high_idx : word; |
fm_high_idx : word; |
||
fm_high_pow : word; |
fm_high_pow : word; |
||
end; |
end; |
||
tpFac_mul = ^tFac_mul; |
tpFac_mul = ^tFac_mul; |
||
tFacMulPow = array of tFac_mul; |
tFacMulPow = array of tFac_mul; |
||
tFactorial = array[0..maxFac-2] of tnum; |
|||
var |
var |
||
Factorial: array[0..maxFac-2] of tnum; |
|||
FacMulPowGes : tFacMulPow; |
FacMulPowGes : tFacMulPow; |
||
Factorial: tFactorial; |
|||
LastSearchFor :tFac_mul; |
LastSearchFor :tFac_mul; |
||
dblLimit : tnum; |
dblLimit : tnum; |
||
function CommatizeUint64(num:Uint64):AnsiString; |
|||
procedure QuickSort(var AI: tFacMulPow; ALo, AHi: Int32); |
|||
var |
var |
||
fromIdx,toIdx :Int32; |
|||
Tmp :tFac_mul; |
|||
Begin |
|||
Pivot : tnum; |
|||
str(num,result); |
|||
Lo, Hi : Int32; |
|||
fromIdx := length(result); |
|||
begin |
|||
toIdx := fromIdx-1; |
|||
if toIdx < 3 then |
|||
exit; |
|||
Pivot := AI[(Lo + Hi) div 2].fm_num; |
|||
toIdx := 4*(toIdx DIV 3)+toIdx MOD 3 +1 ; |
|||
setlength(result,toIdx); |
|||
repeat |
repeat |
||
result[toIdx] := result[FromIdx]; |
|||
while AI[Lo].fm_num < Pivot do |
|||
result[toIdx-1] := result[FromIdx-1]; |
|||
Inc(Lo); |
|||
result[toIdx-2] := result[FromIdx-2]; |
|||
while AI[Hi].fm_num > Pivot do |
|||
result[toIdx-3] := ','; |
|||
dec(toIdx,4); |
|||
if Lo <= Hi then |
|||
dec(FromIdx,3); |
|||
until FromIdx<=3; |
|||
Tmp := AI[Lo]; |
|||
AI[Lo] := AI[Hi]; |
|||
AI[Hi] := Tmp; |
|||
Inc(Lo); |
|||
Dec(Hi); |
|||
end; |
|||
until Lo > Hi; |
|||
if Hi > ALo then |
|||
QuickSort(AI, ALo, Hi) ; |
|||
if Lo < AHi then |
|||
QuickSort(AI, Lo, AHi) ; |
|||
end; |
end; |
||
Line 795: | Line 789: | ||
fac, |
fac, |
||
num : tNum; |
num : tNum; |
||
FacIdx,pow : integer; |
|||
begin |
begin |
||
num := fm.fm_num; |
num := fm.fm_num; |
||
FacIdx := fm.fm_high_idx; |
|||
write(num:20); |
|||
write(CommatizeUint64(num):25,' = '); |
|||
i := fm.fm_high_idx; |
|||
repeat |
repeat |
||
pow := 0; |
|||
fac := Factorial[ |
fac := Factorial[FacIdx]; |
||
while (num>=fac) AND (num mod Fac = 0) do |
while (num>=fac) AND (num mod Fac = 0) do |
||
Begin |
Begin |
||
num := num DIV Fac; |
num := num DIV Fac; |
||
inc( |
inc(pow); |
||
end; |
end; |
||
if |
if pow = 0 then |
||
write(' 1') |
write(' 1') |
||
else |
else |
||
if |
if pow = 1 then |
||
write(' ', |
write(' ',FacIdx+2,'!') |
||
else |
else |
||
write(' (', |
write(' (',FacIdx+2,'!)^',pow); |
||
if num = 1 then |
if num = 1 then |
||
BREAK; |
BREAK; |
||
repeat |
|||
dec(FacIdx); |
|||
while (i>=0 ) AND Not(i in fm.fm_pow) do |
|||
until(FacIdx<0) OR (FacIdx in fm.fm_pow); |
|||
dec(i); |
|||
until |
until FacIdx < 0; |
||
writeln; |
writeln; |
||
end; |
end; |
||
procedure Out_I_th(i: integer); |
procedure Out_I_th(i: integer); |
||
begin |
begin |
||
if i < 0 then |
|||
write(i:8,': '); |
|||
write(i:8,' too small'); |
|||
if i <= High(FacMulPowGes) then |
if i <= High(FacMulPowGes) then |
||
begin |
|||
write(i:6,'-th : '); |
|||
Out_MulFac(i,FacMulPowGes[i-1]) |
Out_MulFac(i,FacMulPowGes[i-1]) |
||
end |
|||
else |
else |
||
writeln('Too big'); |
writeln('Too big'); |
||
end; |
|||
procedure Out_First_N(n: integer); |
|||
var |
|||
s,fmt : AnsiString; |
|||
i,tmp : integer; |
|||
Begin |
|||
if n<1 then |
|||
EXIT; |
|||
writeln('The first ',n,' Jordan-Polia numbers'); |
|||
s := ''; |
|||
If n > Length(FacMulPowGes) then |
|||
n := Length(FacMulPowGes); |
|||
dec(n); |
|||
tmp := length(CommatizeUint64(FacMulPowGes[n].fm_num))+1; |
|||
fmt := '%'+IntToStr(tmp)+'s'; |
|||
tmp := 72 DIV tmp; |
|||
For i := 0 to n do |
|||
Begin |
|||
s += Format(fmt,[CommatizeUint64(FacMulPowGes[i].fm_num)]); |
|||
if (i+1) mod tmp = 0 then |
|||
Begin |
|||
writeln(s); |
|||
s := ''; |
|||
end; |
|||
end; |
|||
if s <>'' then |
|||
writeln(s); |
|||
writeln; |
|||
end; |
end; |
||
Line 850: | Line 879: | ||
inc(idx); |
inc(idx); |
||
end; |
end; |
||
Fillchar(LastSearchFor,SizeOf(LastSearchFor),#0); |
Fillchar(LastSearchFor,SizeOf(LastSearchFor),#0); |
||
LastSearchFor.FM_NUM := 0; |
LastSearchFor.FM_NUM := 0; |
||
dblLimit := 1 shl 53 |
// dblLimit := 1 shl 53; |
||
dblLimit := 1 shl 5; |
|||
end; |
|||
end; |
|||
procedure ResetSearch; |
procedure ResetSearch; |
||
Begin |
Begin |
||
setlength(FacMulPowGes,0); |
setlength(FacMulPowGes,0); |
||
end; |
end; |
||
Line 863: | Line 893: | ||
//generating the first entry with (2!)^n |
//generating the first entry with (2!)^n |
||
var |
var |
||
res_p : tpFac_mul; |
|||
Fac_mul :tFac_mul; |
Fac_mul :tFac_mul; |
||
facPow,Fac : tnum; |
facPow,Fac : tnum; |
||
i, |
i,MaxPowOfFac : integer; |
||
begin |
begin |
||
fac := Factorial[idx]; |
fac := Factorial[idx]; |
||
MaxPowOfFac := trunc(ln(dblLimit)/ln(Fac))+1; |
|||
setlength(res, |
setlength(res,MaxPowOfFac); |
||
fillchar(Fac_Mul,SizeOf(Fac_Mul),#0); |
|||
with Fac_Mul do |
with Fac_Mul do |
||
begin |
begin |
||
Line 878: | Line 907: | ||
fm_high_idx := 0; |
fm_high_idx := 0; |
||
end; |
end; |
||
res_p := @res[0]; |
|||
res[0] := Fac_Mul; |
|||
facPow := 1; |
facPow := 1; |
||
i := 1; |
|||
repeat |
|||
facPow *= Fac; |
facPow *= Fac; |
||
if facPow >dblLimit then |
|||
BREAK; |
|||
with Fac_Mul do |
with Fac_Mul do |
||
begin |
begin |
||
Line 889: | Line 920: | ||
fm_high_pow := i; |
fm_high_pow := i; |
||
end; |
end; |
||
res[i] := Fac_Mul; |
|||
inc(i); |
|||
until i = MaxPowOfFac; |
|||
end; |
|||
setlength(res,i); |
|||
end; |
end; |
||
procedure DelDoublettes(var FMP:tFacMulPow); |
procedure DelDoublettes(var FMP:tFacMulPow); |
||
//throw out doublettes, |
//throw out doublettes, |
||
//the one with highest power in the highest n! survives |
|||
var |
var |
||
pNext,pCurrent : tpFac_mul; |
|||
i, |
i, len,idx : integer; |
||
begin |
begin |
||
len := 0; |
|||
pCurrent := @FMP[0]; |
|||
pNext := pCurrent; |
|||
For i := 0 to High(FMP)-1 do |
For i := 0 to High(FMP)-1 do |
||
begin |
begin |
||
inc( |
inc(pNext); |
||
// don't increment pCurrent if equal |
|||
if pJ^.fm_num = pI^.fm_num then |
|||
// pCurrent gets or stays the highest Value in n!^high_pow |
|||
if pCurrent^.fm_num = pNext^.fm_num then |
|||
Begin |
Begin |
||
idx := |
idx := pCurrent^.fm_high_idx; |
||
if idx < |
if idx < pNext^.fm_high_idx then |
||
pCurrent^ := pNext^ |
|||
else |
else |
||
if idx = |
if idx = pNext^.fm_high_idx then |
||
if |
if pCurrent^.fm_high_pow < pNext^.fm_high_pow then |
||
pCurrent^ := pNext^; |
|||
end |
end |
||
else |
else |
||
begin |
begin |
||
inc( |
inc(len); |
||
inc( |
inc(pCurrent); |
||
pCurrent^ := pNext^; |
|||
end; |
end; |
||
end; |
end; |
||
setlength(FMP, |
setlength(FMP,len); |
||
end; |
|||
procedure QuickSort(var AI: tFacMulPow; ALo, AHi: Int32); |
|||
var |
|||
Tmp :tFac_mul; |
|||
Pivot : tnum; |
|||
Lo, Hi : Int32; |
|||
begin |
|||
Lo := ALo; |
|||
Hi := AHi; |
|||
Pivot := AI[(Lo + Hi) div 2].fm_num; |
|||
repeat |
|||
while AI[Lo].fm_num < Pivot do |
|||
Inc(Lo); |
|||
while AI[Hi].fm_num > Pivot do |
|||
Dec(Hi); |
|||
if Lo <= Hi then |
|||
begin |
|||
Tmp := AI[Lo]; |
|||
AI[Lo] := AI[Hi]; |
|||
AI[Hi] := Tmp; |
|||
Inc(Lo); |
|||
Dec(Hi); |
|||
end; |
|||
until Lo > Hi; |
|||
if Hi > ALo then |
|||
QuickSort(AI, ALo, Hi) ; |
|||
if Lo < AHi then |
|||
QuickSort(AI, Lo, AHi) ; |
|||
end; |
end; |
||
function InsertFacMulPow(var res:tFacMulPow;Facidx:integer):boolean; |
|||
var |
var |
||
Fac, |
Fac,FacPow,NewNum,limit : tnum; |
||
l_res,l_NewMaxPow,idx,i,j : Integer; |
l_res,l_NewMaxPow,idx,i,j : Integer; |
||
begin |
begin |
||
fac := Factorial[Facidx]; |
fac := Factorial[Facidx]; |
||
if length(res)= 0 then |
|||
Begin |
|||
GenerateFirst(Facidx,res); |
|||
EXIT; |
|||
end; |
|||
if fac>dblLimit then |
if fac>dblLimit then |
||
EXIT; |
EXIT(false); |
||
l_NewMaxPow := trunc(ln(dblLimit)/ln(Fac))+1; |
|||
l_res := length(res); |
|||
if length(res)> 0 then |
|||
//calc new length, reduces allocation of big memory chunks |
|||
begin |
|||
l_NewMaxPow := trunc(ln(dblLimit)/ln(Fac))+1; |
|||
idx := High(res); |
|||
l_res := length(res); |
|||
For i := 1 to l_NewMaxPow do |
|||
//calc new length, reduces allocation of big memory chunks |
|||
Begin |
|||
//first original length + length of the new to insert |
|||
limit := dblLimit DIV fac; |
|||
j := l_res+l_NewMaxPow; |
|||
if limit < 1 then |
|||
//find the maximal needed elements which stay below dbllimit |
|||
BREAK; |
|||
// for every Fac^i |
|||
repeat |
|||
idx := High(res); |
|||
FacPow := Fac; |
|||
For i := 1 to l_NewMaxPow do |
|||
inc(j,idx); |
|||
Begin |
|||
fac *=Factorial[Facidx]; |
|||
limit := dblLimit DIV FacPow; |
|||
end; |
|||
if limit < 1 then |
|||
j += l_res+l_NewMaxPow+2; |
|||
BREAK; |
|||
setlength(res,j); |
|||
//search for the right position |
|||
repeat |
|||
dec(idx); |
|||
until res[idx].fm_num<=limit; |
|||
inc(j,idx); |
|||
FacPow *= fac; |
|||
end; |
|||
j += 2; |
|||
setlength(res,j); |
|||
idx := l_res; |
|||
FacPow := fac; |
|||
For j := |
For j := 1 to l_NewMaxPow do |
||
begin |
|||
For i := 0 to l_res-1 do |
|||
begin |
begin |
||
For i := 0 to l_res do |
|||
begin |
|||
NewNum := res[i].fm_num*FacPow; |
|||
if NewNum>dblLimit then |
|||
res[idx]:= res[i]; |
|||
Break; |
|||
res[idx]:= res[i]; |
|||
with res[idx] do |
|||
Begin |
|||
fm_num := NewNum; |
|||
include(fm_pow,Facidx); |
|||
fm_high_idx := Facidx; |
|||
fm_high_pow := j; |
|||
end; |
|||
inc(idx); |
|||
end; |
|||
FacPow *= fac; |
|||
end; |
end; |
||
setlength(res,idx); |
|||
fac *= Factorial[Facidx]; |
|||
QuickSort(res,Low(res),High(res)); |
|||
end; |
|||
DelDoublettes(res); |
|||
end |
|||
QuickSort(res,Low(res),High(res)); |
|||
else |
|||
DelDoublettes(res); |
|||
GenerateFirst(Facidx,res); |
|||
Exit(true); |
|||
end; |
end; |
||
Line 993: | Line 1,058: | ||
BEGIn |
BEGIn |
||
InitFirst; |
InitFirst; |
||
repeat |
repeat |
||
ResetSearch; |
ResetSearch; |
||
i := 0; |
i := 0; |
||
repeat |
repeat |
||
if |
if Not(InsertFacMulPow(FacMulPowGes,i)) then |
||
BREAK; |
|||
else |
|||
break; |
|||
inc(i); |
inc(i); |
||
until i > High(Factorial); |
until i > High(Factorial); |
||
//check if MaxIdx is found |
|||
if (Length(FacMulPowGes) > MaxIdx) then |
if (Length(FacMulPowGes) > MaxIdx) then |
||
begin |
begin |
||
Line 1,008: | Line 1,073: | ||
Begin |
Begin |
||
LastSearchFor := FacMulPowGes[MaxIdx-1]; |
LastSearchFor := FacMulPowGes[MaxIdx-1]; |
||
//the next factorial is to big, so search is done |
|||
if LastSearchFor.fm_num < Factorial[i] then |
if LastSearchFor.fm_num < Factorial[i] then |
||
break; |
break; |
||
end |
end |
||
else |
else |
||
Break; |
Break; |
||
end; |
end; |
||
if dblLimit> HIGH(tNUm) DIV 256 then |
if dblLimit> HIGH(tNUm) DIV 256 then |
||
BREAK; |
BREAK; |
||
dblLimit *= 256; |
dblLimit *= 256; |
||
until false; |
until false; |
||
write('Found ',length(FacMulPowGes),' Jordan-Polia numbers '); |
write('Found ',length(FacMulPowGes),' Jordan-Polia numbers '); |
||
writeln('up to ',dblLimit); |
writeln('up to ',CommatizeUint64(dblLimit)); |
||
writeln; |
writeln; |
||
Out_First_N(50); |
|||
writeln('The first 50 Jordan-Polia numbers'); |
|||
For i := 1 to 50 do |
|||
Begin |
|||
write(FacMulPowGes[i-1].fm_num:5); |
|||
if i mod 10 = 0 then |
|||
writeln; |
|||
end; |
|||
writeln; |
|||
write('The last < 1E8 '); |
write('The last < 1E8 '); |
||
Line 1,040: | Line 1,100: | ||
writeln; |
writeln; |
||
Out_I_th( |
Out_I_th(1); |
||
Out_I_th(100); |
Out_I_th(100); |
||
Out_I_th(800); |
Out_I_th(800); |
||
Line 1,050: | Line 1,110: | ||
{{out|@home}} |
{{out|@home}} |
||
<pre> |
<pre> |
||
Found 3876 Jordan-Polia numbers up to |
Found 3876 Jordan-Polia numbers up to 9,007,199,254,740,992 |
||
The first 50 Jordan-Polia numbers |
The first 50 Jordan-Polia numbers |
||
1 2 4 6 8 12 16 24 32 36 |
1 2 4 6 8 12 16 24 32 36 48 64 |
||
72 96 120 128 144 192 216 240 256 288 384 432 |
|||
480 512 576 720 768 864 960 1,024 1,152 1,296 1,440 1,536 |
|||
1,728 1,920 2,048 2,304 2,592 2,880 3,072 3,456 3,840 4,096 4,320 4,608 |
|||
960 1024 1152 1296 1440 1536 1728 1920 2048 2304 |
|||
5,040 5,184 |
|||
2592 2880 3072 3456 3840 4096 4320 4608 5040 5184 |
|||
The last < 1E8 99532800 (6!)^2 4! (2!)^3 |
|||
The last < 1E8 99,532,800 = (6!)^2 4! (2!)^3 |
|||
100: 92160 6! (2!)^7 |
|||
800: 18345885696 (4!)^7 (2!)^2 |
|||
1050: 139345920000 8! (5!)^3 2! |
|||
1800: 9784472371200 (6!)^2 (4!)^2 (2!)^15 |
|||
2800: 439378587648000 14! 7! |
|||
3800: 7213895789838336 (4!)^8 (2!)^16 |
|||
1-th : 1 = 1 |
|||
real 0m0,002s user 0m0,002s sys 0m0,000s</pre> |
|||
100-th : 92,160 = 6! (2!)^7 |
|||
800-th : 18,345,885,696 = (4!)^7 (2!)^2 |
|||
1050-th : 139,345,920,000 = 8! (5!)^3 2! |
|||
1800-th : 9,784,472,371,200 = (6!)^2 (4!)^2 (2!)^15 |
|||
2800-th : 439,378,587,648,000 = 14! 7! |
|||
3800-th : 7,213,895,789,838,336 = (4!)^8 (2!)^16 |
|||
real 0m0,004s user 0m0,004s sys 0m0,000s</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |