Smallest multiple: Difference between revisions
(julia example) |
m (→extended: extended to show count of digits til 2 billion) |
||
Line 167: | Line 167: | ||
</pre> |
</pre> |
||
===extended=== |
===extended=== |
||
fascinating find, that the count of digits is nearly a constant x upper rangelimit.<br> The number of factors is the count of primes til limit.See GetFactorList.<br>No need for calculating lcm(lcm(lcm(1,2),3),4..) or prime decomposition<BR> |
|||
Using prime sieve. |
Using prime sieve. |
||
<lang pascal>{$IFDEF FPC} |
<lang pascal>{$IFDEF FPC} |
||
{$MODE DELPHI} |
{$MODE DELPHI} {$Optimization On} |
||
{$ELSE} |
{$ELSE} |
||
{$APPTAYPE CONSOLE} |
{$APPTAYPE CONSOLE} |
||
Line 180: | Line 180: | ||
{$ENDIF} |
{$ENDIF} |
||
sysutils; //format |
sysutils; //format |
||
const |
const |
||
MAX_LIMIT = 2*1000*1000; |
|||
UpperLimit = MAX_LIMIT+1000;// so to find a prime beyond MAX_LIMIT |
|||
MAX_UINT64 = 46; |
|||
MAX_UINT64 = 46;// unused.Limit to get an Uint64 output |
|||
type |
type |
||
tFactors = array of Uint32; |
tFactors = array of Uint32; |
||
tprimelist = array of byte; |
tprimelist = array of byte; |
||
var |
var |
||
primeDeltalist : tPrimelist; |
|||
factors, |
|||
saveFactors:tFactors; |
|||
saveFactorsIdx, |
|||
maxFactorsIdx : Uint32; |
|||
procedure Init_Primes; |
procedure Init_Primes; |
||
var |
var |
||
pPrime : pByte; |
pPrime : pByte; |
||
p |
p,i,delta,cnt: NativeUInt; |
||
begin |
begin |
||
setlength( |
setlength(primeDeltalist,UpperLimit+3*8+1); |
||
pPrime := @ |
pPrime := @primeDeltalist[0]; |
||
//delete multiples of 2,3 |
//delete multiples of 2,3 |
||
i := 0; |
i := 0; |
||
Line 206: | Line 209: | ||
inc(i,24); |
inc(i,24); |
||
until i>UpperLimit; |
until i>UpperLimit; |
||
cnt := 2;// 2,3 |
|||
p := 5; |
p := 5; |
||
delta := 1;//5-3 |
|||
repeat |
repeat |
||
if pPrime[p] <> 0 then |
if pPrime[p] <> 0 then |
||
Line 213: | Line 218: | ||
if i > UpperLimit then |
if i > UpperLimit then |
||
break; |
break; |
||
inc(cnt); |
|||
pPrime[p-2*delta] := delta; |
|||
delta := 0; |
|||
repeat |
repeat |
||
pPrime[i] := 0; |
pPrime[i] := 0; |
||
Line 219: | Line 227: | ||
end; |
end; |
||
inc(p,2); |
inc(p,2); |
||
inc(delta); |
|||
until p*p>UpperLimit; |
until p*p>UpperLimit; |
||
setlength(saveFactors,cnt); |
|||
pPrime[1] := 0; |
|||
//convert to delta |
|||
pPrime[2] := 1; |
|||
repeat |
|||
pPrime[3] := 1; |
|||
if pPrime[p]<> 0 then |
|||
begin |
|||
pPrime[p-2*delta] := delta; |
|||
inc(cnt); |
|||
delta := 0; |
|||
end; |
|||
inc(p,2); |
|||
inc(delta); |
|||
until p > UpperLimit; |
|||
setlength(factors,cnt); |
|||
factors[0] := 2; |
|||
factors[1] := 3; |
|||
i := 2; |
|||
p := 5; |
|||
repeat |
|||
factors[i] := p; |
|||
p += 2*pPrime[p]; |
|||
i += 1; |
|||
until i >= cnt; |
|||
setlength(primeDeltalist,0); |
|||
// writeln(length(savefactors)); writeln(length(factors)); |
|||
end; |
end; |
||
{$IFDEF USE_GMP} |
{$IFDEF USE_GMP} |
||
procedure ConvertToMPZ(const factors:tFactors); |
procedure ConvertToMPZ(const factors:tFactors;dgtCnt:UInt32); |
||
const |
|||
c19Digits = QWord(10*1000000)*1000000*1000000; |
|||
var |
var |
||
mp : mpz_t; |
mp,mpdiv : mpz_t; |
||
s : AnsiString; |
s : AnsiString; |
||
rest,last : Uint64; |
|||
f : Uint32; |
|||
i :int32; |
|||
begin |
begin |
||
//Init and allocate space |
|||
mpz_init(mp); |
|||
mpz_init_set_ui(mp,0); |
|||
mpz_init(mpdiv); |
|||
mpz_ui_pow_ui(mpdiv,10,dgtCnt); |
|||
mpz_add(mp,mp,mpdiv); |
|||
mpz_add_ui(mp,mp,1); |
|||
mpz_set_ui(mp,1); |
mpz_set_ui(mp,1); |
||
for i := 0 to high(factors) do |
|||
i := maxFactorsIdx; |
|||
mpz_mul_ui(mp,mp,factors[i]); |
|||
rest := 1; |
|||
repeat |
|||
setlength(s,i+10); |
|||
last := rest; |
|||
mpz_get_str(@s[1],10,mp); |
|||
f := factors[i]; |
|||
rest *= f; |
|||
while not(s[i] in['0'..'9']) do |
|||
if rest div f <> last then |
|||
begin |
|||
mpz_mul_ui(mp,mp,last); |
|||
rest := f; |
|||
end; |
|||
dec(i); |
dec(i); |
||
until i < 0; |
|||
setlength(s,i+1); |
|||
mpz_mul_ui(mp,mp,rest); |
|||
if length(s)> 22 then |
|||
If dgtcnt>40 then |
|||
begin |
begin |
||
rest := mpz_fdiv_ui(mp,c19Digits); |
|||
move(s[i-9],s[13],10); |
|||
s |
s := '..'+Format('%.19u',[rest]); |
||
mpz_fdiv_q_ui (mpdiv,mpdiv,c19Digits); |
|||
setlength(s,22); |
|||
mpz_fdiv_q(mp,mp,mpdiv); |
|||
rest := mpz_get_ui(mp); |
|||
writeln(rest:19,s); |
|||
mpz_clear(mpdiv); |
|||
end |
|||
else |
|||
Begin |
|||
setlength(s,dgtCnt+1000); |
|||
mpz_get_str(@s[1],10,mp); |
|||
writeln(s); |
|||
i := length(s); |
|||
while not(s[i] in['0'..'9']) do |
|||
dec(i); |
|||
setlength(s,i+1); |
|||
writeln(s); |
|||
end; |
end; |
||
writeln(s); |
|||
mpz_clear(mp); |
mpz_clear(mp); |
||
end; |
end; |
||
Line 256: | Line 316: | ||
procedure CheckDigits(const factors:tFactors); |
procedure CheckDigits(const factors:tFactors); |
||
var |
var |
||
dgtcnt : extended; |
|||
i : integer; |
i : integer; |
||
begin |
begin |
||
dgtcnt := 0; |
|||
i := 0; |
|||
repeat |
|||
digcnt += ln(factors[i]); |
|||
dgtcnt += ln(factors[i]); |
|||
inc(i); |
|||
writeln(' has ',length(factors):10,' factors and ',i:10,' digits'); |
|||
until i > maxFactorsIdx; |
|||
dgtcnt := trunc(dgtcnt/ln(10))+1; |
|||
writeln(' has ',maxFactorsIdx+1:10,' factors and ',dgtcnt:10:0,' digits'); |
|||
{$IFDEF USE_GMP} |
{$IFDEF USE_GMP} |
||
i := trunc(dgtcnt); |
|||
if i < 1000*1000 then |
|||
ConvertToMPZ(factors); |
|||
ConvertToMPZ(factors,i); |
|||
{$ENDIF} |
{$ENDIF} |
||
end; |
end; |
||
Line 274: | Line 338: | ||
i : integer; |
i : integer; |
||
begin |
begin |
||
if |
if maxFactorsIdx >15 then |
||
Exit(0); |
Exit(0); |
||
result := 1; |
result := 1; |
||
for i := 0 to |
for i := 0 to maxFactorsIdx do |
||
result *= factors[i]; |
result *= factors[i]; |
||
end; |
end; |
||
Line 287: | Line 351: | ||
begin |
begin |
||
result := ''; |
result := ''; |
||
for i := 0 to |
for i := 0 to maxFactorsIdx-1 do |
||
begin |
begin |
||
str(factors[i],s); |
str(factors[i],s); |
||
result += s+'*'; |
result += s+'*'; |
||
end; |
end; |
||
str(factors[ |
str(factors[maxFactorsIdx],s); |
||
result += s; |
result += s; |
||
end; |
end; |
||
Line 298: | Line 362: | ||
procedure GetFactorList(var factors:tFactors;max:Uint32); |
procedure GetFactorList(var factors:tFactors;max:Uint32); |
||
var |
var |
||
p,f,lf : Uint32; |
|||
n,f,lf : Uint32; |
|||
BEGIN |
BEGIN |
||
p := 2; |
|||
n := 2; |
|||
lf := 0; |
lf := 0; |
||
saveFactors[lf] := p; |
|||
setlength(factors,lf); |
|||
while p*p <= max do |
|||
while n*n <= max do |
|||
Begin |
Begin |
||
saveFactors[lf] := p; |
|||
f := p*p; |
|||
while f*p <= max do |
|||
setlength(factors,lf+1); |
|||
f |
f*= p; |
||
factors[lf] := f; |
|||
while f*n <= max do |
|||
inc(lf); |
|||
factors[lf] |
p := factors[lf]; |
||
if p= 0 then HALT; |
|||
end; |
|||
inc(n); |
|||
end; |
end; |
||
if lf>0 then |
|||
//the rest are all the primes up to max |
|||
saveFactorsIdx := lf-1; |
|||
For n := n to max do |
|||
repeat |
|||
if pPrime[n]<>0 then |
|||
inc(lf) |
|||
until factors[lf]>Max; |
|||
maxFactorsIdx := lf-1; |
|||
inc(lf); |
|||
end; |
|||
end; |
end; |
||
procedure Check(var factors:tFactors;max:Uint32); |
procedure Check(var factors:tFactors;max:Uint32); |
||
var |
|||
i: Uint32; |
|||
begin |
begin |
||
GetFactorList(factors,max); |
GetFactorList(factors,max); |
||
write(max:10,': '); |
write(max:10,': '); |
||
if |
if maxFactorsIdx>15 then |
||
CheckDigits(factors) |
|||
else |
else |
||
writeln(ConvertToUint64(factors):21,' = ',ConvertToStr(factors)); |
writeln(ConvertToUint64(factors):21,' = ',ConvertToStr(factors)); |
||
for i := 0 to saveFactorsIdx do |
|||
factors[i] := savefactors[i]; |
|||
end; |
end; |
||
var |
var |
||
factors:tFactors; |
|||
max: Uint32; |
max: Uint32; |
||
BEGIN |
BEGIN |
||
Init_Primes; |
Init_Primes; |
||
max := |
max := 2; |
||
repeat |
repeat |
||
check(factors,max); |
check(factors,max); |
||
max *=10; |
max *=10; |
||
until max > |
until max > MAX_LIMIT; |
||
For max := MAX_UINT64 downto 2 do |
|||
writeln; |
|||
For max := 10 to 20 do // < MAX_UINT64 |
|||
check(factors,max); |
check(factors,max); |
||
{$IFDEF WINDOWS} |
{$IFDEF WINDOWS} |
||
READLN; |
READLN; |
||
{$ENDIF} |
{$ENDIF} |
||
END. |
END. |
||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre style="height:300px"> |
<pre style="height:300px"> |
||
TIO.RUN Real time: |
TIO.RUN Real time: 1.161 s User time: 1.106 s Sys. time: 0.049 s CPU share: 99.49 % |
||
2: 2 = 2 |
|||
20: 232792560 = 16*9*5*7*11*13*17*19 |
|||
3372935888..0066992000 |
|||
200: has 46 factors and 90 digits |
|||
3372935888329262646..8060677390066992000 |
|||
2000: has 303 factors and 867 digits |
2000: has 303 factors and 867 digits |
||
1511177948774443153..3786415805463680000 |
|||
1511177948..5463680000 |
|||
20000: has 2262 factors and 8676 digits |
20000: has 2262 factors and 8676 digits |
||
4879325627288270518..7411295098112000000 |
|||
4879325627..8112000000 |
|||
200000: has 17984 factors and 86871 digits |
200000: has 17984 factors and 86871 digits |
||
3942319728529926377..9513860925440000000 |
|||
2000000: has 148933 factors and 868639 digits |
2000000: has 148933 factors and 868639 digits |
||
8467191629995920178..6480233472000000000 |
|||
46: 9419588158802421600 = 32*27*25*7*11*13*17*19*23*29*31*37*41*43 |
|||
{ at home |
|||
45: 9419588158802421600 = 32*27*25*7*11*13*17*19*23*29*31*37*41*43 |
|||
20000000: has 1270607 factors and 8686151 digits |
|||
44: 9419588158802421600 = 32*27*25*7*11*13*17*19*23*29*31*37*41*43 |
|||
1681437413936981958..6706037760000000000 |
|||
43: 9419588158802421600 = 32*27*25*7*11*13*17*19*23*29*31*37*41*43 |
|||
200000000: has 11078937 factors and 86857606 digits |
|||
42: 219060189739591200 = 32*27*25*7*11*13*17*19*23*29*31*37*41 |
|||
2000000000: has 98222287 factors and 868583388 digits |
|||
41: 219060189739591200 = 32*27*25*7*11*13*17*19*23*29*31*37*41 |
|||
} |
|||
40: 5342931457063200 = 32*27*25*7*11*13*17*19*23*29*31*37 |
|||
39: 5342931457063200 = 32*27*25*7*11*13*17*19*23*29*31*37 |
|||
38: 5342931457063200 = 32*27*25*7*11*13*17*19*23*29*31*37 |
|||
37: 5342931457063200 = 32*27*25*7*11*13*17*19*23*29*31*37 |
|||
36: 144403552893600 = 32*27*25*7*11*13*17*19*23*29*31 |
|||
35: 144403552893600 = 32*27*25*7*11*13*17*19*23*29*31 |
|||
34: 144403552893600 = 32*27*25*7*11*13*17*19*23*29*31 |
|||
33: 144403552893600 = 32*27*25*7*11*13*17*19*23*29*31 |
|||
32: 144403552893600 = 32*27*25*7*11*13*17*19*23*29*31 |
|||
31: 72201776446800 = 16*27*25*7*11*13*17*19*23*29*31 |
|||
30: 2329089562800 = 16*27*25*7*11*13*17*19*23*29 |
|||
29: 2329089562800 = 16*27*25*7*11*13*17*19*23*29 |
|||
28: 80313433200 = 16*27*25*7*11*13*17*19*23 |
|||
27: 80313433200 = 16*27*25*7*11*13*17*19*23 |
|||
26: 26771144400 = 16*9*25*7*11*13*17*19*23 |
|||
25: 26771144400 = 16*9*25*7*11*13*17*19*23 |
|||
24: 5354228880 = 16*9*5*7*11*13*17*19*23 |
|||
23: 5354228880 = 16*9*5*7*11*13*17*19*23 |
|||
22: 232792560 = 16*9*5*7*11*13*17*19 |
|||
21: 232792560 = 16*9*5*7*11*13*17*19 |
|||
20: 232792560 = 16*9*5*7*11*13*17*19 |
|||
19: 232792560 = 16*9*5*7*11*13*17*19 |
|||
18: 12252240 = 16*9*5*7*11*13*17 |
|||
17: 12252240 = 16*9*5*7*11*13*17 |
|||
16: 720720 = 16*9*5*7*11*13 |
|||
15: 360360 = 8*9*5*7*11*13 |
|||
14: 360360 = 8*9*5*7*11*13 |
|||
13: 360360 = 8*9*5*7*11*13 |
|||
12: 27720 = 8*9*5*7*11 |
|||
11: 27720 = 8*9*5*7*11 |
|||
10: 2520 = 8*9*5*7 |
10: 2520 = 8*9*5*7 |
||
11: 27720 = 8*9*5*7*11 |
|||
12: 27720 = 8*9*5*7*11 |
|||
13: 360360 = 8*9*5*7*11*13 |
|||
14: 360360 = 8*9*5*7*11*13 |
|||
15: 360360 = 8*9*5*7*11*13 |
|||
16: 720720 = 16*9*5*7*11*13 |
|||
17: 12252240 = 16*9*5*7*11*13*17 |
|||
18: 12252240 = 16*9*5*7*11*13*17 |
|||
19: 232792560 = 16*9*5*7*11*13*17*19 |
|||
20: 232792560 = 16*9*5*7*11*13*17*19 |
|||
</pre> |
</pre> |
||
Revision as of 08:41, 22 October 2021
- Task
Task description is taken from Project Euler
(https://projecteuler.net/problem=5)
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
- Related
ALGOL 68
Uses Algol 68G's LONG LONG INT which has specifiable precision.
<lang algol68>BEGIN # find the smallest number that is divisible by each of the numbers 1..n #
# translation of the Wren sample # PR precision 1000 PR # set the precision of LONG LONG INT # PR read "primes.incl.a68" PR # returns the lowest common multiple of the numbers 1 : n # PROC lcm = ( INT n )LONG LONG INT: BEGIN # sieve the primes to n # []BOOL prime = PRIMESIEVE n; LONG LONG INT result := 1; FOR p TO UPB prime DO IF prime[ p ] THEN LONG LONG INT f := p; # f will be set to the # WHILE f * p <= n DO f *:= p OD; # highest multiple of p <= n # result *:= f FI OD; result END # lcm # ; # returns a string representation of n with commas # PROC commatise = ( LONG LONG INT n )STRING: BEGIN STRING result := ""; STRING unformatted = whole( n, 0 ); INT ch count := 0; FOR c FROM UPB unformatted BY -1 TO LWB unformatted DO IF ch count <= 2 THEN ch count +:= 1 ELSE ch count := 1; "," +=: result FI; unformatted[ c ] +=: result OD; result END; # commatise # print( ( "The LCMs of the numbers 1 to N inclusive is:", newline ) ); []INT tests = ( 10, 20, 200, 2000 ); FOR i FROM LWB tests TO UPB tests DO print( ( whole( tests[ i ], -5 ), ": ", commatise( lcm( tests[ i ] ) ), newline ) ) OD
END</lang>
- Output:
10: 2,520 20: 232,792,560 200: 337,293,588,832,926,264,639,465,766,794,841,407,432,394,382,785,157,234,228,847,021,917,234,018,060,677,390,066,992,000 2000: 151,117,794,877,444,315,307,536,308,337,572,822,173,736,308,853,579,339,903,227,904,473,000,476,322,347,234,655,122,160,866,668,946,941,993,951,014,270,933,512,030,194,957,221,371,956,828,843,521,568,082,173,786,251,242,333,157,830,450,435,623,211,664,308,500,316,844,478,617,809,101,158,220,672,108,895,053,508,829,266,120,497,031,742,749,376,045,929,890,296,052,805,527,212,315,382,805,219,353,316,270,742,572,401,962,035,464,878,235,703,759,464,796,806,075,131,056,520,079,836,955,770,415,021,318,508,272,982,103,736,658,633,390,411,347,759,000,563,271,226,062,182,345,964,184,167,346,918,225,243,856,348,794,013,355,418,404,695,826,256,911,622,054,015,423,611,375,261,945,905,974,225,257,659,010,379,414,787,547,681,984,112,941,581,325,198,396,634,685,659,217,861,208,771,400,322,507,388,161,967,513,719,166,366,839,894,214,040,787,733,471,287,845,629,833,993,885,413,462,225,294,548,785,581,641,804,620,417,256,563,685,280,586,511,301,918,399,010,451,347,815,776,570,842,790,738,545,306,707,750,937,624,267,501,103,840,324,470,083,425,714,138,183,905,657,667,736,579,430,274,197,734,179,172,691,637,931,540,695,631,396,056,193,786,415,805,463,680,000
Factor
<lang factor>USING: math.functions math.ranges prettyprint sequences ;
20 [1,b] 1 [ lcm ] reduce .</lang>
- Output:
232792560
Go
<lang go>package main
import (
"fmt" "math/big" "rcu"
)
func lcm(n int) *big.Int {
lcm := big.NewInt(1) t := new(big.Int) for _, p := range rcu.Primes(n) { f := p for f*p <= n { f *= p } lcm.Mul(lcm, t.SetUint64(uint64(f))) } return lcm
}
func main() {
fmt.Println("The LCMs of the numbers 1 to N inclusive is:") for _, i := range []int{10, 20, 200, 2000} { fmt.Printf("%4d: %s\n", i, lcm(i)) }
}</lang>
- Output:
The LCMs of the numbers 1 to N inclusive is: 10: 2520 20: 232792560 200: 337293588832926264639465766794841407432394382785157234228847021917234018060677390066992000 2000: 151117794877444315307536308337572822173736308853579339903227904473000476322347234655122160866668946941993951014270933512030194957221371956828843521568082173786251242333157830450435623211664308500316844478617809101158220672108895053508829266120497031742749376045929890296052805527212315382805219353316270742572401962035464878235703759464796806075131056520079836955770415021318508272982103736658633390411347759000563271226062182345964184167346918225243856348794013355418404695826256911622054015423611375261945905974225257659010379414787547681984112941581325198396634685659217861208771400322507388161967513719166366839894214040787733471287845629833993885413462225294548785581641804620417256563685280586511301918399010451347815776570842790738545306707750937624267501103840324470083425714138183905657667736579430274197734179172691637931540695631396056193786415805463680000
Julia
<lang julia>julia> foreach(x -> @show(lcm(x)), [1:10, 1:20, big"1":200, big"1":2000]) lcm(x) = 2520 lcm(x) = 232792560 lcm(x) = 337293588832926264639465766794841407432394382785157234228847021917234018060677390066992000 lcm(x) = 151117794877444315307536308337572822173736308853579339903227904473000476322347234655122160866668946941993951014270933512030194957221371956828843521568082173786251242333157830450435623211664308500316844478617809101158220672108895053508829266120497031742749376045929890296052805527212315382805219353316270742572401962035464878235703759464796806075131056520079836955770415021318508272982103736658633390411347759000563271226062182345964184167346918225243856348794013355418404695826256911622054015423611375261945905974225257659010379414787547681984112941581325198396634685659217861208771400322507388161967513719166366839894214040787733471287845629833993885413462225294548785581641804620417256563685280586511301918399010451347815776570842790738545306707750937624267501103840324470083425714138183905657667736579430274197734179172691637931540695631396056193786415805463680000 </lang>
Pascal
Here the simplest way, like Raku, check the highest exponent of every prime in range
Using harded coded primes.
<lang pascal>{$IFDEF FPC}
{$MODE DELPHI}
{$ELSE}
{$APPTAYPE CONSOLE}
{$ENDIF} const
smallprimes : array[0..10] of Uint32 = (2,3,5,7,11,13,17,19,23,29,31); MAX = 20;
function getmaxfac(pr: Uint32): Uint32; //get the pr^highest exponent of prime used in 2 .. MAX var
i,fac : integer;
Begin
result := pr; while pr*result <= MAX do result *= pr;
end;
var
n,pr,prIdx : Uint32;
BEGIN
n := 1; prIdx := 0; pr := smallprimes[prIdx]; repeat pr := smallprimes[prIdx]; n *= getmaxfac(pr); inc(prIdx); pr := smallprimes[prIdx]; until pr>MAX; writeln(n);
{$IFDEF WINDOWS}
READLN;
{$ENDIF} END. </lang>
- Output:
232792560
extended
fascinating find, that the count of digits is nearly a constant x upper rangelimit.
The number of factors is the count of primes til limit.See GetFactorList.
No need for calculating lcm(lcm(lcm(1,2),3),4..) or prime decomposition
Using prime sieve.
<lang pascal>{$IFDEF FPC}
{$MODE DELPHI} {$Optimization On}
{$ELSE}
{$APPTAYPE CONSOLE}
{$ENDIF} {$DEFINE USE_GMP} uses
{$IFDEF USE_GMP} gmp, {$ENDIF} sysutils; //format
const
MAX_LIMIT = 2*1000*1000; UpperLimit = MAX_LIMIT+1000;// so to find a prime beyond MAX_LIMIT MAX_UINT64 = 46;// unused.Limit to get an Uint64 output
type
tFactors = array of Uint32; tprimelist = array of byte;
var
primeDeltalist : tPrimelist; factors, saveFactors:tFactors; saveFactorsIdx, maxFactorsIdx : Uint32;
procedure Init_Primes; var
pPrime : pByte; p,i,delta,cnt: NativeUInt;
begin
setlength(primeDeltalist,UpperLimit+3*8+1); pPrime := @primeDeltalist[0]; //delete multiples of 2,3 i := 0; repeat //take care of endianess //0706050403020100 pUint64(@pPrime[i+0])^ := $0100010000000100; pUint64(@pPrime[i+8])^ := $0000010001000000; pUint64(@pPrime[i+16])^:= $0100000001000100; inc(i,24); until i>UpperLimit; cnt := 2;// 2,3 p := 5; delta := 1;//5-3 repeat if pPrime[p] <> 0 then begin i := p*p; if i > UpperLimit then break; inc(cnt); pPrime[p-2*delta] := delta; delta := 0; repeat pPrime[i] := 0; inc(i,2*p); until i>UpperLimit; end; inc(p,2); inc(delta); until p*p>UpperLimit; setlength(saveFactors,cnt); //convert to delta repeat if pPrime[p]<> 0 then begin pPrime[p-2*delta] := delta; inc(cnt); delta := 0; end; inc(p,2); inc(delta); until p > UpperLimit; setlength(factors,cnt); factors[0] := 2; factors[1] := 3; i := 2; p := 5; repeat factors[i] := p; p += 2*pPrime[p]; i += 1; until i >= cnt; setlength(primeDeltalist,0);
// writeln(length(savefactors)); writeln(length(factors)); end;
{$IFDEF USE_GMP} procedure ConvertToMPZ(const factors:tFactors;dgtCnt:UInt32); const
c19Digits = QWord(10*1000000)*1000000*1000000;
var
mp,mpdiv : mpz_t; s : AnsiString; rest,last : Uint64; f : Uint32; i :int32;
begin
//Init and allocate space mpz_init_set_ui(mp,0); mpz_init(mpdiv); mpz_ui_pow_ui(mpdiv,10,dgtCnt); mpz_add(mp,mp,mpdiv); mpz_add_ui(mp,mp,1); mpz_set_ui(mp,1);
i := maxFactorsIdx; rest := 1; repeat last := rest; f := factors[i]; rest *= f; if rest div f <> last then begin mpz_mul_ui(mp,mp,last); rest := f; end; dec(i); until i < 0; mpz_mul_ui(mp,mp,rest);
If dgtcnt>40 then begin rest := mpz_fdiv_ui(mp,c19Digits); s := '..'+Format('%.19u',[rest]); mpz_fdiv_q_ui (mpdiv,mpdiv,c19Digits); mpz_fdiv_q(mp,mp,mpdiv); rest := mpz_get_ui(mp); writeln(rest:19,s); mpz_clear(mpdiv); end else Begin setlength(s,dgtCnt+1000); mpz_get_str(@s[1],10,mp); writeln(s); i := length(s); while not(s[i] in['0'..'9']) do dec(i); setlength(s,i+1); writeln(s); end; mpz_clear(mp);
end; {$ENDIF}
procedure CheckDigits(const factors:tFactors); var
dgtcnt : extended; i : integer;
begin
dgtcnt := 0; i := 0; repeat dgtcnt += ln(factors[i]); inc(i); until i > maxFactorsIdx; dgtcnt := trunc(dgtcnt/ln(10))+1; writeln(' has ',maxFactorsIdx+1:10,' factors and ',dgtcnt:10:0,' digits'); {$IFDEF USE_GMP} i := trunc(dgtcnt); if i < 1000*1000 then ConvertToMPZ(factors,i); {$ENDIF}
end;
function ConvertToUint64(const factors:tFactors):Uint64; var
i : integer;
begin
if maxFactorsIdx >15 then Exit(0); result := 1; for i := 0 to maxFactorsIdx do result *= factors[i];
end;
function ConvertToStr(const factors:tFactors):Ansistring; var
s : Ansistring; i : integer;
begin
result := ; for i := 0 to maxFactorsIdx-1 do begin str(factors[i],s); result += s+'*'; end; str(factors[maxFactorsIdx],s); result += s;
end;
procedure GetFactorList(var factors:tFactors;max:Uint32); var
p,f,lf : Uint32;
BEGIN
p := 2; lf := 0; saveFactors[lf] := p; while p*p <= max do Begin saveFactors[lf] := p; f := p*p; while f*p <= max do f*= p; factors[lf] := f; inc(lf); p := factors[lf]; if p= 0 then HALT; end; if lf>0 then saveFactorsIdx := lf-1; repeat inc(lf) until factors[lf]>Max; maxFactorsIdx := lf-1;
end;
procedure Check(var factors:tFactors;max:Uint32); var
i: Uint32;
begin
GetFactorList(factors,max); write(max:10,': '); if maxFactorsIdx>15 then CheckDigits(factors) else writeln(ConvertToUint64(factors):21,' = ',ConvertToStr(factors)); for i := 0 to saveFactorsIdx do factors[i] := savefactors[i];
end;
var
max: Uint32;
BEGIN
Init_Primes;
max := 2; repeat check(factors,max); max *=10; until max > MAX_LIMIT;
writeln; For max := 10 to 20 do // < MAX_UINT64 check(factors,max);
{$IFDEF WINDOWS}
READLN;
{$ENDIF} END. </lang>
- Output:
TIO.RUN Real time: 1.161 s User time: 1.106 s Sys. time: 0.049 s CPU share: 99.49 % 2: 2 = 2 20: 232792560 = 16*9*5*7*11*13*17*19 200: has 46 factors and 90 digits 3372935888329262646..8060677390066992000 2000: has 303 factors and 867 digits 1511177948774443153..3786415805463680000 20000: has 2262 factors and 8676 digits 4879325627288270518..7411295098112000000 200000: has 17984 factors and 86871 digits 3942319728529926377..9513860925440000000 2000000: has 148933 factors and 868639 digits 8467191629995920178..6480233472000000000 { at home 20000000: has 1270607 factors and 8686151 digits 1681437413936981958..6706037760000000000 200000000: has 11078937 factors and 86857606 digits 2000000000: has 98222287 factors and 868583388 digits } 10: 2520 = 8*9*5*7 11: 27720 = 8*9*5*7*11 12: 27720 = 8*9*5*7*11 13: 360360 = 8*9*5*7*11*13 14: 360360 = 8*9*5*7*11*13 15: 360360 = 8*9*5*7*11*13 16: 720720 = 16*9*5*7*11*13 17: 12252240 = 16*9*5*7*11*13*17 18: 12252240 = 16*9*5*7*11*13*17 19: 232792560 = 16*9*5*7*11*13*17*19 20: 232792560 = 16*9*5*7*11*13*17*19
Raku
Exercise with some larger values as well.
<lang perl6>say "$_: ", [lcm] 2..$_ for <10 20 200 2000></lang>
- Output:
10: 2520 20: 232792560 200: 337293588832926264639465766794841407432394382785157234228847021917234018060677390066992000 2000: 151117794877444315307536308337572822173736308853579339903227904473000476322347234655122160866668946941993951014270933512030194957221371956828843521568082173786251242333157830450435623211664308500316844478617809101158220672108895053508829266120497031742749376045929890296052805527212315382805219353316270742572401962035464878235703759464796806075131056520079836955770415021318508272982103736658633390411347759000563271226062182345964184167346918225243856348794013355418404695826256911622054015423611375261945905974225257659010379414787547681984112941581325198396634685659217861208771400322507388161967513719166366839894214040787733471287845629833993885413462225294548785581641804620417256563685280586511301918399010451347815776570842790738545306707750937624267501103840324470083425714138183905657667736579430274197734179172691637931540695631396056193786415805463680000
Ring
<lang ring> see "working..." + nl see "Smallest multiple is:" + nl n = 0
while true
n++ flag = 0 for m = 1 to 20 if n % m = 0 flag += 1 ok next if flag = 20 see "" + n + nl exit ok
end
see "done..." + nl </lang>
- Output:
working... Smallest multiple is: 232792560 done...
Wren
We don't really need a computer for the task as set because it's just the product of the maximum prime powers <= 20 which is : 16 x 9 x 5 x 7 x 11 x 13 x 17 x 19 = 232,792,560.
More formally and quite quick by Wren standards at 0.017 seconds: <lang ecmascript>import "./math" for Int import "./big" for BigInt import "./fmt" for Fmt
var lcm = Fn.new { |n|
var primes = Int.primeSieve(n) var lcm = BigInt.one for (p in primes) { var f = p while (f * p <= n) f = f * p lcm = lcm * f } return lcm
}
System.print("The LCMs of the numbers 1 to N inclusive is:") for (i in [10, 20, 200, 2000]) Fmt.print("$,5d: $,i", i, lcm.call(i))</lang>
- Output:
The LCMs of the numbers 1 to N inclusive is: 10: 2,520 20: 232,792,560 200: 337,293,588,832,926,264,639,465,766,794,841,407,432,394,382,785,157,234,228,847,021,917,234,018,060,677,390,066,992,000 2,000: 151,117,794,877,444,315,307,536,308,337,572,822,173,736,308,853,579,339,903,227,904,473,000,476,322,347,234,655,122,160,866,668,946,941,993,951,014,270,933,512,030,194,957,221,371,956,828,843,521,568,082,173,786,251,242,333,157,830,450,435,623,211,664,308,500,316,844,478,617,809,101,158,220,672,108,895,053,508,829,266,120,497,031,742,749,376,045,929,890,296,052,805,527,212,315,382,805,219,353,316,270,742,572,401,962,035,464,878,235,703,759,464,796,806,075,131,056,520,079,836,955,770,415,021,318,508,272,982,103,736,658,633,390,411,347,759,000,563,271,226,062,182,345,964,184,167,346,918,225,243,856,348,794,013,355,418,404,695,826,256,911,622,054,015,423,611,375,261,945,905,974,225,257,659,010,379,414,787,547,681,984,112,941,581,325,198,396,634,685,659,217,861,208,771,400,322,507,388,161,967,513,719,166,366,839,894,214,040,787,733,471,287,845,629,833,993,885,413,462,225,294,548,785,581,641,804,620,417,256,563,685,280,586,511,301,918,399,010,451,347,815,776,570,842,790,738,545,306,707,750,937,624,267,501,103,840,324,470,083,425,714,138,183,905,657,667,736,579,430,274,197,734,179,172,691,637,931,540,695,631,396,056,193,786,415,805,463,680,000