Practical numbers: Difference between revisions
Content added Content deleted
m (→{{header|alternative}}: only memorizing heigher divisors) |
MaiconSoft (talk | contribs) m (Fix pascal version to run in delphi) |
||
Line 138: | Line 138: | ||
{$ELSE} |
{$ELSE} |
||
{$APPTYPE CONSOLE} |
{$APPTYPE CONSOLE} |
||
{$ENDIF} |
{$ENDIF} |
||
uses |
uses |
||
sysutils |
sysutils |
||
{$IFNDEF FPC} |
|||
,Windows |
|||
{$ENDIF} |
|||
; |
|||
const |
|||
LOW_DIVS = 0; |
|||
HIGH_DIVS = 2048 - 1; |
|||
type |
type |
||
tdivs = record |
tdivs = record |
||
DivsVal: array[LOW_DIVS..HIGH_DIVS] of Uint32; |
|||
⚫ | |||
DivsMaxIdx, |
|||
⚫ | |||
DivsNum, |
|||
⚫ | |||
⚫ | |||
var |
var |
||
Divs: tDivs; |
Divs: tDivs; |
||
HasSum |
HasSum: array of byte; |
||
procedure GetDivisors(var Divs:tdivs;n:Uint32); |
procedure GetDivisors(var Divs: tdivs; n: Uint32); |
||
//calc all divisors,keep sorted |
//calc all divisors,keep sorted |
||
var |
var |
||
i,quot,ug, |
i, quot, ug, og: UInt32; |
||
sum: UInt64; |
sum: UInt64; |
||
begin |
|||
Begin |
|||
with Divs do |
with Divs do |
||
begin |
|||
DivsNum := n; |
DivsNum := n; |
||
sum := 0; |
sum := 0; |
||
ug := |
ug := 0; |
||
og := |
og := HIGH_DIVS; |
||
i := 1; |
i := 1; |
||
while i*i < n do |
while i * i < n do |
||
begin |
begin |
||
quot := n div i; |
quot := n div i; |
||
if n - quot * i = 0 then |
|||
begin |
|||
DivsVal[og] := quot; |
DivsVal[og] := quot; |
||
Divs.DivsVal[ug] := i; |
Divs.DivsVal[ug] := i; |
||
inc(sum,quot+i); |
inc(sum, quot + i); |
||
dec(og); |
dec(og); |
||
inc(ug); |
inc(ug); |
||
Line 178: | Line 189: | ||
inc(i); |
inc(i); |
||
end; |
end; |
||
if i * i = n then |
|||
begin |
|||
DivsVal[og] := i; |
DivsVal[og] := i; |
||
inc(sum,i); |
inc(sum, i); |
||
dec(og); |
dec(og); |
||
end; |
end; |
||
//move higher divisors down |
//move higher divisors down |
||
while og < |
while og < high_DIVS do |
||
begin |
begin |
||
inc(og); |
inc(og); |
||
Line 191: | Line 202: | ||
inc(ug); |
inc(ug); |
||
end; |
end; |
||
DivsMaxIdx := ug-2; |
DivsMaxIdx := ug - 2; |
||
DivsSumProp := sum-n; |
DivsSumProp := sum - n; |
||
end;//with |
end; //with |
||
end; |
end; |
||
function SumAllSetsForPractical(Limit:Uint32):boolean; |
function SumAllSetsForPractical(Limit: Uint32): boolean; |
||
//mark sum and than shift by next divisor == add |
//mark sum and than shift by next divisor == add |
||
//for practical numbers every sum must be marked |
//for practical numbers every sum must be marked |
||
var |
var |
||
hs0, |
hs0, hs1: pByte; |
||
idx,j,loLimit,maxlimit, |
idx, j, loLimit, maxlimit, delta: NativeUint; |
||
begin |
|||
Begin |
|||
Limit := trunc(Limit*(Limit/Divs.DivsSumProp)); |
Limit := trunc(Limit * (Limit / Divs.DivsSumProp)); |
||
loLimit := 0; |
|||
maxlimit := 0; |
maxlimit := 0; |
||
hs0 := @HasSum[0]; |
hs0 := @HasSum[0]; |
||
hs0[0] := 1;//empty set |
hs0[0] := 1; //empty set |
||
for idx := 0 to Divs.DivsMaxIdx do |
for idx := 0 to Divs.DivsMaxIdx do |
||
begin |
|||
delta := Divs.DivsVal[idx]; |
delta := Divs.DivsVal[idx]; |
||
hs1 := @hs0[delta]; |
hs1 := @hs0[delta]; |
||
for j := maxlimit downto 0 do |
|||
hs1[j] := |
hs1[j] := hs1[j] or hs0[j]; |
||
maxlimit |
maxlimit := maxlimit + delta; |
||
while hs0[ |
while hs0[loLimit] <> 0 do |
||
inc( |
inc(loLimit); |
||
//IF there is a 0 < delta, it will never be set |
//IF there is a 0 < delta, it will never be set |
||
//IF there are more than the Limit set, |
//IF there are more than the Limit set, |
||
//it will be copied by the following Delta's |
//it will be copied by the following Delta's |
||
if ( |
if (loLimit < delta) or (loLimit > Limit) then |
||
Break; |
Break; |
||
end; |
end; |
||
result := ( |
result := (loLimit > Limit); |
||
end; |
end; |
||
function isPractical(n:Uint32):boolean; |
function isPractical(n: Uint32): boolean; |
||
var |
var |
||
i:NativeInt; |
i: NativeInt; |
||
sum:NativeUInt; |
sum: NativeUInt; |
||
begin |
|||
Begin |
|||
if n= 1 then |
if n = 1 then |
||
EXIT(True); |
EXIT(True); |
||
if ODD(n) then |
if ODD(n) then |
||
EXIT(false); |
EXIT(false); |
||
if (n > 2) |
if (n > 2) and not ((n mod 4 = 0) or (n mod 6 = 0)) then |
||
EXIT(false); |
EXIT(false); |
||
GetDivisors(Divs,n); |
GetDivisors(Divs, n); |
||
i := n-1; |
i := n - 1; |
||
sum := Divs.DivsSumProp; |
sum := Divs.DivsSumProp; |
||
if sum < i then |
if sum < i then |
||
result := false |
result := false |
||
else |
else |
||
begin |
|||
if length(HasSum) > sum + 1 + 1 then |
|||
FillChar(HasSum[0],sum+1,#0) |
FillChar(HasSum[0], sum + 1, #0) |
||
else |
else |
||
begin |
|||
setlength(HasSum,0); |
setlength(HasSum, 0); |
||
setlength(HasSum,sum+8+1); |
setlength(HasSum, sum + 8 + 1); |
||
end; |
end; |
||
result:=SumAllSetsForPractical(i); |
result := SumAllSetsForPractical(i); |
||
end; |
end; |
||
end; |
end; |
||
procedure OutIsPractical(n:nativeInt); |
procedure OutIsPractical(n: nativeInt); |
||
begin |
begin |
||
if isPractical(n) then |
|||
writeln(n,' is practical') |
writeln(n, ' is practical') |
||
else |
else |
||
writeln(n,' is not practical'); |
writeln(n, ' is not practical'); |
||
end; |
end; |
||
const |
const |
||
ColCnt = 10; |
|||
MAX = 333; |
|||
var |
var |
||
T0 |
T0: Int64; |
||
n,col, |
n, col, count: NativeInt; |
||
Begin |
|||
begin |
|||
col:=ColCnt; |
col := ColCnt; |
||
count := 0; |
count := 0; |
||
for n := 1 to MAX do |
|||
if isPractical(n) then |
if isPractical(n) then |
||
begin |
begin |
||
write(n:5); |
write(n: 5); |
||
inc(count); |
inc(count); |
||
dec(col); |
dec(col); |
||
if col = 0 then |
if col = 0 then |
||
begin |
|||
writeln; |
writeln; |
||
col :=ColCnt; |
col := ColCnt; |
||
end; |
end; |
||
end; |
end; |
||
writeln; |
writeln; |
||
writeln('There are ',count,' pratical numbers from 1 to ',MAX); |
writeln('There are ', count, ' pratical numbers from 1 to ', MAX); |
||
writeln; |
writeln; |
||
Line 297: | Line 310: | ||
OutIsPractical(5384); |
OutIsPractical(5384); |
||
OutIsPractical(1441440); |
OutIsPractical(1441440); |
||
writeln(Divs.DivsNum,' has ',Divs.DivsMaxIdx+1,' proper divisors'); |
writeln(Divs.DivsNum, ' has ', Divs.DivsMaxIdx + 1, ' proper divisors'); |
||
writeln((GetTickCount64-T0)/1000:10:3,' s'); |
writeln((GetTickCount64 - T0) / 1000: 10: 3, ' s'); |
||
T0 := GetTickCount64; |
T0 := GetTickCount64; |
||
OutIsPractical(99998640); |
OutIsPractical(99998640); |
||
writeln(Divs.DivsNum,' has ',Divs.DivsMaxIdx+1,' proper divisors '); |
writeln(Divs.DivsNum, ' has ', Divs.DivsMaxIdx + 1, ' proper divisors '); |
||
writeln((GetTickCount64-T0)/1000:10:3,' s'); |
writeln((GetTickCount64 - T0) / 1000: 10: 3, ' s'); |
||
T0 := GetTickCount64; |
T0 := GetTickCount64; |
||
OutIsPractical(99998640); |
OutIsPractical(99998640); |
||
writeln(Divs.DivsNum,' has ',Divs.DivsMaxIdx+1,' proper divisors '); |
writeln(Divs.DivsNum, ' has ', Divs.DivsMaxIdx + 1, ' proper divisors '); |
||
writeln((GetTickCount64-T0)/1000:10:3,' s'); |
writeln((GetTickCount64 - T0) / 1000: 10: 3, ' s'); |
||
setlength(HasSum,0); |
setlength(HasSum, 0); |
||
{$IFNDEF UNIX} readln; {$ENDIF} |
|||
⚫ | |||
end. |
|||
⚫ | |||
{{out}} |
{{out}} |
||
<pre> TIO.RUN. |
<pre> TIO.RUN. |