RosettaCodeData/Task/Perfect-numbers/M2000-Interpreter/perfect-numbers.m2000
2023-07-01 13:44:08 -04:00

71 lines
2.4 KiB
Text

Module PerfectNumbers {
Function Is_Perfect(n as decimal) {
s=1 : sN=Sqrt(n)
last= n=sN*sN
t=n
If n mod 2=0 then s+=2+n div 2
i=3 : sN--
While i<sN {
if n mod i=0 then t=n div i :i=max.data(n div t, i): s+=t+ i
i++
}
=n=s
}
Inventory Known1=2@, 3@
IsPrime=lambda Known1 (x as decimal) -> {
=0=1
if exist(Known1, x) then =1=1 : exit
if x<=5 OR frac(x) then {if x == 2 OR x == 3 OR x == 5 then Append Known1, x : =1=1
Break}
if frac(x/2) else exit
if frac(x/3) else exit
x1=sqrt(x):d = 5@
{if frac(x/d ) else exit
d += 2: if d>x1 then Append Known1, x : =1=1 : exit
if frac(x/d) else exit
d += 4: if d<= x1 else Append Known1, x : =1=1: exit
loop}
}
\\ Check a perfect and a non perfect number
p=2 : n=3 : n1=2
Document Doc$
IsPerfect( 0, 28)
IsPerfect( 0, 1544)
While p<32 { ' max 32
if isprime(2^p-1@) then {
perf=(2^p-1@)*2@^(p-1@)
Rem Print perf
\\ decompose pretty fast the Perferct Numbers
\\ all have a series of 2 and last a prime equal to perf/2^(p-1)
inventory queue factors
For i=1 to p-1 {
Append factors, 2@
}
Append factors, perf/2^(p-1)
\\ end decompose
Rem Print factors
IsPerfect(factors, Perf)
}
p++
}
Clipboard Doc$
\\ exit here. No need for Exit statement
Sub IsPerfect(factors, n)
s=false
if n<10000 or type$(factors)<>"Inventory" then {
s=Is_Perfect(n)
} else {
local mm=each(factors, 1, -2), f =true
while mm {if eval(mm)<>2 then f=false
}
if f then if n/2@**(len(mm)-1)= factors(len(factors)-1!) then s=true
}
Local a$=format$("{0} is {1}perfect number", n, If$(s->"", "not "))
Doc$=a$+{
}
Print a$
End Sub
}
PerfectNumbers