Sphenic numbers: Difference between revisions
Content added Content deleted
m (→{{header|AppleScript}}: Duh! The sort's not needed if the sphenics are initially stored in the list slots they index.) |
m (→{{header|Free Pascal}}: get rid of sorting. Tested to one billion) |
||
Line 391: | Line 391: | ||
{{trans|Wren}} Output Format {{trans|AppleScript}} |
{{trans|Wren}} Output Format {{trans|AppleScript}} |
||
Most of the time, ~ 75% in this case, is spent with sort. |
Most of the time, ~ 75% in this case, is spent with sort. |
||
Now changed to use sieve of erathostenes and insert sphenic numbers in that array,So no sort is needed. |
|||
A little bit lengthy... |
|||
<syntaxhighlight lang=pascal> |
<syntaxhighlight lang=pascal> |
||
program sphenic; |
program sphenic; |
||
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} |
|||
{$IFDEF WINDOWS}{$APPTYPE CONSOLE}{$ENDIF} |
|||
const |
const |
||
Limit= 1000*1000; |
Limit= 1*1000*1000; |
||
LimitPrime = Limit div (2*3); |
|||
type |
|||
primeCount = 15224; |
|||
tPrimesSieve = array of boolean; |
|||
var |
|||
tElement = Uint32; |
|||
tarrElement = array of tElement; |
|||
tpPrimes = pBoolean; |
|||
procedure GetPrimes; |
|||
//trial division |
|||
var |
var |
||
PrimeSieve : tPrimesSieve; |
|||
p,p2,i,maxIdx,maxSqrtPrimeIdx : Uint32; |
|||
primes : tarrElement; |
|||
begin |
|||
sphenics : tarrElement; |
|||
setlength(Primes,primeCount); |
|||
primes[0] := 2; |
|||
function BuildWheel(pPrimes:tpPrimes;lmt:Uint32): longint; |
|||
maxIdx := 0; |
|||
var |
|||
maxSqrtPrimeIdx := 0; |
|||
wheelSize, wpno, pr, pw, i, k: NativeUint; |
|||
p2:= sqr(primes[maxSqrtPrimeIdx]); |
|||
wheelprimes: array[0..15] of byte; |
|||
For p := 3 to LimitPrime do |
|||
begin |
begin |
||
pr := 1;//the mother of all numbers 1 ;-) |
|||
if p2 <=p then |
|||
pPrimes[1] := True; |
|||
begin |
|||
WheelSize := 1; |
|||
inc(maxSqrtPrimeIdx); |
|||
p2 := sqr(primes[maxSqrtPrimeIdx]); |
|||
wpno := 0; |
|||
i := 0; |
|||
repeat |
repeat |
||
Inc(pr); |
|||
if p mod primes[i] = 0 then |
|||
//pw = pr projected in wheel of wheelsize |
|||
BREAK; |
|||
pw := pr; |
|||
if pw > wheelsize then |
|||
Dec(pw, wheelsize); |
|||
if i >= maxSqrtPrimeIdx then |
|||
if pPrimes[pw] then |
|||
begin |
|||
k := WheelSize + 1; |
|||
//turn the wheel (pr-1)-times |
|||
for i := 1 to pr - 1 do |
|||
begin |
|||
Inc(k, WheelSize); |
|||
if k < lmt then |
|||
move(pPrimes[1], pPrimes[k - WheelSize], WheelSize) |
|||
else |
|||
begin |
|||
move(pPrimes[1], pPrimes[k - WheelSize], Limit - WheelSize * i); |
|||
break; |
|||
end; |
|||
end; |
|||
Dec(k); |
|||
if k > lmt then |
|||
k := lmt; |
|||
wheelPrimes[wpno] := pr; |
|||
pPrimes[pr] := False; |
|||
Inc(wpno); |
|||
WheelSize := k;//the new wheelsize |
|||
//sieve multiples of the new found prime |
|||
i := pr; |
|||
i := i * i; |
|||
while i <= k do |
|||
begin |
|||
pPrimes[i] := False; |
|||
Inc(i, pr); |
|||
end; |
|||
end; |
|||
until WheelSize >= lmt; |
|||
//re-insert wheel-primes 1 still stays prime |
|||
while wpno > 0 do |
|||
begin |
begin |
||
Dec(wpno); |
|||
pPrimes[wheelPrimes[wpno]] := True; |
|||
end; |
end; |
||
result := pr; |
|||
end; |
end; |
||
setlength(primes,maxidx+1); |
|||
end; |
|||
procedure |
procedure Sieve(pPrimes:tpPrimes;lmt:Uint32); |
||
procedure QSort(L, R: Int32); |
|||
var |
var |
||
sieveprime, fakt, i: UInt32; |
|||
Tmp, Pivot: Uint32; |
|||
begin |
begin |
||
sieveprime := BuildWheel(pPrimes,lmt); |
|||
if R - L < 1 then exit; |
|||
I := L; J := R; |
|||
{$push}{$q-}{$r-}Pivot := A[(L + R) shr 1];{$pop} |
|||
repeat |
repeat |
||
repeat |
|||
while A[I] < Pivot do Inc(I); |
|||
Inc(sieveprime); |
|||
until pPrimes[sieveprime]; |
|||
fakt := Lmt div sieveprime; |
|||
while Not(pPrimes[fakt]) do |
|||
dec(fakt); |
|||
if fakt < sieveprime then |
|||
BREAK; |
|||
i := (fakt + 1) mod 6; |
|||
if i = 0 then |
|||
QSort(L, J); |
|||
i := 4; |
|||
repeat |
|||
pPrimes[sieveprime * fakt] := False; |
|||
repeat |
|||
Dec(fakt, i); |
|||
i := 6 - i; |
|||
until pPrimes[fakt]; |
|||
if fakt < sieveprime then |
|||
BREAK; |
|||
until False; |
|||
until False; |
|||
pPrimes[1] := False;//remove 1 |
|||
end; |
end; |
||
procedure InitAndGetPrimes; |
|||
var |
|||
prCnt,i,idx,lmt : UInt32; |
|||
begin |
begin |
||
setlength(PrimeSieve,Limit+1); |
|||
QSort(0, High(A)); |
|||
lmt := Limit DIV (2*3); |
|||
if Lmt < 65536 then |
|||
setlength(Primes,6542) |
|||
else |
|||
setlength(Primes,trunc(lmt/(ln(lmt)-1.1))); |
|||
Sieve(@PrimeSieve[0],lmt); |
|||
prCnt := 0; |
|||
for i := 1 to Lmt do |
|||
Begin |
|||
if PrimeSieve[i] then |
|||
begin |
|||
primes[prCnt] := i; |
|||
inc(prCnt); |
|||
end; |
|||
end; |
|||
setlength(primes,prCnt); |
|||
end; |
end; |
||
function binary_search(value: Uint32): Int32; |
function binary_search(value: Uint32;const A:tarrElement): Int32; |
||
var |
var |
||
p : Uint32; |
p : Uint32; |
||
l, m, h: |
l, m, h: tElement; |
||
begin |
begin |
||
l := Low(primes); |
l := Low(primes); |
||
Line 469: | Line 533: | ||
begin |
begin |
||
m := (l + h) div 2; |
m := (l + h) div 2; |
||
p := |
p := A[m]; |
||
if p > value then |
if p > value then |
||
begin |
begin |
||
Line 493: | Line 557: | ||
p1,p2,p,i : Uint32; |
p1,p2,p,i : Uint32; |
||
begin |
begin |
||
fillchar(PrimeSieve[0],Limit+1,#0); |
|||
i := 0; |
i := 0; |
||
idx1 := trunc(exp(1/3*ln(Limit))); |
idx1 := trunc(exp(1/3*ln(Limit))); |
||
idx1 := binary_search(idx1)-1; |
idx1 := binary_search(idx1,Primes)-1; |
||
idx3 := idx1+2; |
idx3 := idx1+2; |
||
For i1 := 0 to idx1 do |
For i1 := 0 to idx1 do |
||
Line 501: | Line 566: | ||
p1 := primes[i1]; |
p1 := primes[i1]; |
||
idx2 := trunc(sqrt(Limit DIV p1)); |
idx2 := trunc(sqrt(Limit DIV p1)); |
||
idx2:= binary_search(idx2)+1; |
idx2:= binary_search(idx2,Primes)+1; |
||
For i2 := i1+1 to idx2 do |
For i2 := i1+1 to idx2 do |
||
begin |
begin |
||
Line 510: | Line 575: | ||
if p > Limit then |
if p > Limit then |
||
break; |
break; |
||
//mark as sphenic number |
|||
PrimeSieve[p]:= true; |
|||
inc(i); |
inc(i); |
||
end; |
end; |
||
end; |
end; |
||
end; |
end; |
||
//insert |
|||
setlength(sphenics,i); |
setlength(sphenics,i); |
||
p := 0; |
|||
QuickSort(sphenics); |
|||
For i := 0 to Limit do |
|||
begin |
|||
if PrimeSieve[i] then |
|||
begin |
|||
sphenics[p] := i; |
|||
inc(p); |
|||
end; |
|||
end; |
|||
end; |
end; |
||
Line 524: | Line 599: | ||
end; |
end; |
||
function CheckTriplets(i:Uint32):boolean; |
function CheckTriplets(i:Uint32):boolean;inline; |
||
begin |
begin |
||
CheckTriplets:= |
CheckTriplets:= PrimeSieve[i] AND PrimeSieve[i+1] AND PrimeSieve[i+2]; |
||
(sphenics[i+1]+1=sphenics[i+2]); |
|||
end; |
end; |
||
Line 533: | Line 607: | ||
i,j,t5000 : Uint32; |
i,j,t5000 : Uint32; |
||
begin |
begin |
||
InitAndGetPrimes; |
|||
GetPrimes; |
|||
setlength(sphenics,21*Limit div 100+100);//203,834,084 for Limit 1E9 |
|||
CreateSphenics; |
CreateSphenics; |
||
writeln('Sphenic numbers < 1,000:'); |
writeln('Sphenic numbers < 1,000:'); |
||
i := |
i := 0; |
||
repeat |
repeat |
||
if sphenics[i] > 1000 then |
if sphenics[i] > 1000 then |
||
break; |
break; |
||
write(sphenics[i]:4); |
write(sphenics[i]:4); |
||
inc(i); |
|||
if i Mod 15 = 0 then |
if i Mod 15 = 0 then |
||
writeln; |
writeln; |
||
inc(i); |
|||
until i>= High(sphenics); |
until i>= High(sphenics); |
||
writeln; |
writeln; |
||
Line 551: | Line 624: | ||
j := 0; |
j := 0; |
||
repeat |
repeat |
||
if CheckTriplets(i) then |
if CheckTriplets(sphenics[i]) then |
||
Begin |
Begin |
||
OutTriplet(i); |
OutTriplet(i); |
||
Line 570: | Line 643: | ||
writeln('There are ',length(sphenics),' sphenic numbers < ',limit); |
writeln('There are ',length(sphenics),' sphenic numbers < ',limit); |
||
repeat |
repeat |
||
if CheckTriplets(i) then |
if CheckTriplets(sphenics[i]) then |
||
Begin |
Begin |
||
inc(j); |
inc(j); |
||
Line 579: | Line 652: | ||
until i+2 >high(sphenics); |
until i+2 >high(sphenics); |
||
writeln('There are ',j,' sphenic triplets numbers < ',limit); |
writeln('There are ',j,' sphenic triplets numbers < ',limit); |
||
writeln('The 200,000th sphenic number is ',sphenics[200000]); |
writeln('The 200,000th sphenic number is ',sphenics[200000-1]); |
||
write('The 5,000th sphenic triplet is ');OutTriplet(T5000); |
write('The 5,000th sphenic triplet is ');OutTriplet(T5000); |
||
end. |
end. |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
{{out}} |
{{out|@TIO.RUN}} |
||
<pre> |
<pre> |
||
Sphenic numbers < 1,000: |
Sphenic numbers < 1,000: |
||
Line 607: | Line 680: | ||
The 200,000th sphenic number is 966467 |
The 200,000th sphenic number is 966467 |
||
The 5,000th sphenic triplet is {918005,918006,918007} |
The 5,000th sphenic triplet is {918005,918006,918007} |
||
Real time: 0.096 s User time: 0.067 s Sys. time: 0.028 s |
|||
@home (4.4 Ghz Ryzen 5600G): |
|||
There are 2086746 sphenic numbers < 10000000 |
|||
There are 20710806 sphenic numbers < 100000000 |
|||
There are 203834084 sphenic numbers < 1000000000 |
|||
There are 55576 sphenic triplets numbers < 10000000 |
|||
There are 527138 sphenic triplets numbers < 100000000 |
|||
There are 4824694 sphenic triplets numbers < 1000000000 |
|||
real 0m5,530s |
|||
</pre> |
</pre> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
{{trans|Wren}} |
{{trans|Wren}} |