Zumkeller numbers: Difference between revisions
Tag: Rollback |
|||
(13 intermediate revisions by 8 users not shown) | |||
Line 37: | Line 37: | ||
{{trans|D}} |
{{trans|D}} |
||
< |
<syntaxhighlight lang="11l">F getDivisors(n) |
||
V divs = [1, n] |
V divs = [1, n] |
||
V i = 2 |
V i = 2 |
||
Line 112: | Line 112: | ||
I count % 8 == 0 |
I count % 8 == 0 |
||
print() |
print() |
||
i += 2</ |
i += 2</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 145: | Line 145: | ||
=={{header|AArch64 Assembly}}== |
=={{header|AArch64 Assembly}}== |
||
{{works with|as|Raspberry Pi 3B version Buster 64 bits}} |
{{works with|as|Raspberry Pi 3B version Buster 64 bits}} |
||
< |
<syntaxhighlight lang="AArch64 Assembly"> |
||
/* ARM assembly AARCH64 Raspberry PI 3B */ |
/* ARM assembly AARCH64 Raspberry PI 3B */ |
||
/* program zumkellex641.s */ |
/* program zumkellex641.s */ |
||
Line 633: | Line 633: | ||
/* for this file see task include a file in language AArch64 assembly */ |
/* for this file see task include a file in language AArch64 assembly */ |
||
.include "../includeARM64.inc" |
.include "../includeARM64.inc" |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Output:}} |
{{Output:}} |
||
<pre> |
<pre> |
||
Line 661: | Line 661: | ||
On my machine, this takes about 0.28 seconds to perform the two main searches and a further 107 to do the stretch task. However, the latter time can be dramatically reduced to 1.7 seconds with the cheat of knowing beforehand that the first 200 or so odd Zumkellers not ending with 5 are divisible by 63. The "abundant number" optimisation's now used with odd numbers, but the cheat-free running time was only two to three seconds longer without it. |
On my machine, this takes about 0.28 seconds to perform the two main searches and a further 107 to do the stretch task. However, the latter time can be dramatically reduced to 1.7 seconds with the cheat of knowing beforehand that the first 200 or so odd Zumkellers not ending with 5 are divisible by 63. The "abundant number" optimisation's now used with odd numbers, but the cheat-free running time was only two to three seconds longer without it. |
||
< |
<syntaxhighlight lang="applescript">-- Sum n's proper divisors. |
||
on aliquotSum(n) |
on aliquotSum(n) |
||
if (n < 2) then return 0 |
if (n < 2) then return 0 |
||
Line 819: | Line 819: | ||
local cheating |
local cheating |
||
set cheating to false |
set cheating to false |
||
doTask(cheating)</ |
doTask(cheating)</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
< |
<syntaxhighlight lang="applescript">"1st 220 Zumkeller numbers: |
||
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 |
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 |
||
102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 |
102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 |
||
Line 845: | Line 845: | ||
351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 |
351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 |
||
812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 |
812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 |
||
1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377"</ |
1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377"</syntaxhighlight> |
||
=={{header|ARM Assembly}}== |
=={{header|ARM Assembly}}== |
||
{{works with|as|Raspberry Pi}} |
{{works with|as|Raspberry Pi}} |
||
< |
<syntaxhighlight lang="ARM Assembly"> |
||
/* ARM assembly Raspberry PI */ |
/* ARM assembly Raspberry PI */ |
||
/* program zumkeller4.s */ |
/* program zumkeller4.s */ |
||
Line 1,527: | Line 1,527: | ||
/***************************************************/ |
/***************************************************/ |
||
.include "../affichage.inc" |
.include "../affichage.inc" |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre> |
<pre> |
||
Program start |
Program start |
||
Line 1,560: | Line 1,560: | ||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
using System.Linq; |
using System.Linq; |
||
Line 1,655: | Line 1,655: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The first 220 Zumkeller numbers are: |
<pre>The first 220 Zumkeller numbers are: |
||
Line 1,684: | Line 1,684: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp>#include <iostream"> |
||
#include <cmath> |
#include <cmath> |
||
#include <vector> |
#include <vector> |
||
Line 1,826: | Line 1,826: | ||
// if we get here it ain't no zum |
// if we get here it ain't no zum |
||
return false; |
return false; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,871: | Line 1,871: | ||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="d">import std.algorithm; |
||
import std.stdio; |
import std.stdio; |
||
Line 1,961: | Line 1,961: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The first 220 Zumkeller numbers are: |
<pre>The first 220 Zumkeller numbers are: |
||
Line 1,988: | Line 1,988: | ||
960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 |
960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 |
||
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</pre> |
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</pre> |
||
=={{header|EasyLang}}== |
|||
<syntaxhighlight lang=text> |
|||
proc divisors n . divs[] . |
|||
divs[] = [ 1 n ] |
|||
for i = 2 to sqrt n |
|||
if n mod i = 0 |
|||
j = n / i |
|||
divs[] &= i |
|||
if i <> j |
|||
divs[] &= j |
|||
. |
|||
. |
|||
. |
|||
. |
|||
func ispartsum divs[] sum . |
|||
if sum = 0 |
|||
return 1 |
|||
. |
|||
if len divs[] = 0 |
|||
return 0 |
|||
. |
|||
last = divs[len divs[]] |
|||
len divs[] -1 |
|||
if last > sum |
|||
return ispartsum divs[] sum |
|||
. |
|||
if ispartsum divs[] sum = 1 |
|||
return 1 |
|||
. |
|||
return ispartsum divs[] (sum - last) |
|||
. |
|||
func iszumkeller n . |
|||
divisors n divs[] |
|||
for v in divs[] |
|||
sum += v |
|||
. |
|||
if sum mod 2 = 1 |
|||
return 0 |
|||
. |
|||
if n mod 2 = 1 |
|||
abund = sum - 2 * n |
|||
return if abund > 0 and abund mod 2 = 0 |
|||
. |
|||
return ispartsum divs[] (sum / 2) |
|||
. |
|||
# |
|||
print "The first 220 Zumkeller numbers are:" |
|||
i = 2 |
|||
repeat |
|||
if iszumkeller i = 1 |
|||
write i & " " |
|||
count += 1 |
|||
. |
|||
until count = 220 |
|||
i += 1 |
|||
. |
|||
print "\n\nThe first 40 odd Zumkeller numbers are:" |
|||
count = 0 |
|||
i = 3 |
|||
repeat |
|||
if iszumkeller i = 1 |
|||
write i & " " |
|||
count += 1 |
|||
. |
|||
until count = 40 |
|||
i += 2 |
|||
. |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
The first 220 Zumkeller numbers are: |
|||
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 |
|||
The first 40 odd Zumkeller numbers are: |
|||
945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 |
|||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
This task uses [https://rosettacode.org/wiki/Sum_of_divisors#F.23] |
This task uses [https://rosettacode.org/wiki/Sum_of_divisors#F.23] |
||
< |
<syntaxhighlight lang="fsharp"> |
||
// Zumkeller numbers: Nigel Galloway. May 16th., 2021 |
// Zumkeller numbers: Nigel Galloway. May 16th., 2021 |
||
let rec fG n g=match g with h::_ when h>=n->h=n |h::t->fG n t || fG(n-h) t |_->false |
let rec fG n g=match g with h::_ when h>=n->h=n |h::t->fG n t || fG(n-h) t |_->false |
||
Line 2,002: | Line 2,080: | ||
Seq.initInfinite((*)2>>(+)1)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 40|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n" |
Seq.initInfinite((*)2>>(+)1)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 40|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n" |
||
Seq.initInfinite((*)2>>(+)1)|>Seq.filter(fun n->n%10<>5)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 40|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n" |
Seq.initInfinite((*)2>>(+)1)|>Seq.filter(fun n->n%10<>5)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 40|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n" |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,011: | Line 2,089: | ||
81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377 |
81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377 |
||
</pre> |
</pre> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
{{works with|Factor|0.99 2019-10-06}} |
{{works with|Factor|0.99 2019-10-06}} |
||
< |
<syntaxhighlight lang="factor">USING: combinators grouping io kernel lists lists.lazy math |
||
math.primes.factors memoize prettyprint sequences ; |
math.primes.factors memoize prettyprint sequences ; |
||
Line 2,054: | Line 2,133: | ||
"First 40 odd Zumkeller numbers not ending with 5:" print |
"First 40 odd Zumkeller numbers not ending with 5:" print |
||
40 odd-zumkellers-no-5 8 show</ |
40 odd-zumkellers-no-5 8 show</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,085: | Line 2,164: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 2,175: | Line 2,254: | ||
} |
} |
||
fmt.Println() |
fmt.Println() |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,208: | Line 2,287: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
{{Trans|Python}} |
{{Trans|Python}} |
||
< |
<syntaxhighlight lang="haskell">import Data.List (group, sort) |
||
import Data.List.Split (chunksOf) |
import Data.List.Split (chunksOf) |
||
import Data.Numbers.Primes (primeFactors) |
import Data.Numbers.Primes (primeFactors) |
||
Line 2,280: | Line 2,359: | ||
justifyRight :: Int -> Char -> String -> String |
justifyRight :: Int -> Char -> String -> String |
||
justifyRight n c = (drop . length) <*> (replicate n c <>)</ |
justifyRight n c = (drop . length) <*> (replicate n c <>)</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>First 220 Zumkeller numbers: |
<pre>First 220 Zumkeller numbers: |
||
Line 2,313: | Line 2,392: | ||
=={{header|J}}== |
=={{header|J}}== |
||
Implementation:< |
Implementation:<syntaxhighlight lang="J>divisors=: {{ \:~ */@>,{ (^ i.@>:)&.">/ __ q: y }} |
||
zum=: {{ |
zum=: {{ |
||
if. 2|s=. +/divs=. divisors y do. 0 |
if. 2|s=. +/divs=. divisors y do. 0 |
||
Line 2,319: | Line 2,398: | ||
else. s=. -:s for_d. divs do. if. d<:s do. s=. s-d end. end. s=0 |
else. s=. -:s for_d. divs do. if. d<:s do. s=. s-d end. end. s=0 |
||
end. |
end. |
||
}}@></ |
}}@></syntaxhighlight> |
||
Task examples:< |
Task examples:<syntaxhighlight lang="J"> 10 22$1+I.zum 1+i.1000 NB. first 220 Zumkeller numbers |
||
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 |
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 |
||
108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 |
108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 |
||
Line 2,341: | Line 2,420: | ||
351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 |
351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 |
||
812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 |
812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 |
||
1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</ |
1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
< |
<syntaxhighlight lang="java"> |
||
import java.util.ArrayList; |
import java.util.ArrayList; |
||
import java.util.Collections; |
import java.util.Collections; |
||
Line 2,456: | Line 2,535: | ||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 2,497: | Line 2,576: | ||
generates a stream of partitions is easily transformed into a |
generates a stream of partitions is easily transformed into a |
||
specialized function that prunes irrelevant partitions efficiently. |
specialized function that prunes irrelevant partitions efficiently. |
||
< |
<syntaxhighlight lang="jq"># The factors, sorted |
||
def factors: |
def factors: |
||
. as $num |
. as $num |
||
Line 2,563: | Line 2,642: | ||
end |
end |
||
| true) |
| true) |
||
// false;</ |
// false;</syntaxhighlight><syntaxhighlight lang="jq">## The tasks: |
||
"First 220:", limit(220; range(2; infinite) | select(is_zumkeller)), |
"First 220:", limit(220; range(2; infinite) | select(is_zumkeller)), |
||
"" |
"" |
||
"First 40 odd:", limit(40; range(3; infinite; 2) | select(is_zumkeller))</ |
"First 40 odd:", limit(40; range(3; infinite; 2) | select(is_zumkeller))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,589: | Line 2,668: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">using Primes |
||
function factorize(n) |
function factorize(n) |
||
Line 2,637: | Line 2,716: | ||
println("\n\nFirst 40 odd Zumkeller numbers not ending with 5:") |
println("\n\nFirst 40 odd Zumkeller numbers not ending with 5:") |
||
printconditionalnum((n) -> isodd(n) && (string(n)[end] != '5') && iszumkeller(n), 40, 8) |
printconditionalnum((n) -> isodd(n) && (string(n)[end] != '5') && iszumkeller(n), 40, 8) |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
First 220 Zumkeller numbers: |
First 220 Zumkeller numbers: |
||
Line 2,671: | Line 2,750: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="scala">import java.util.ArrayList |
||
import kotlin.math.sqrt |
import kotlin.math.sqrt |
||
Line 2,779: | Line 2,858: | ||
return divisors |
return divisors |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>First 220 Zumkeller numbers: |
<pre>First 220 Zumkeller numbers: |
||
Line 2,807: | Line 2,886: | ||
=={{header|Lobster}}== |
=={{header|Lobster}}== |
||
< |
<syntaxhighlight lang="Lobster">import std |
||
// Derived from Julia and Python versions |
// Derived from Julia and Python versions |
||
Line 2,867: | Line 2,946: | ||
print "\n\n40 odd Zumkeller numbers:" |
print "\n\n40 odd Zumkeller numbers:" |
||
printZumkellers(40, true) |
printZumkellers(40, true) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,903: | Line 2,982: | ||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="Mathematica">ClearAll[ZumkellerQ] |
||
ZumkellerQ[n_] := Module[{d = Divisors[n], t, ds, x}, |
ZumkellerQ[n_] := Module[{d = Divisors[n], t, ds, x}, |
||
ds = Total[d]; |
ds = Total[d]; |
||
Line 2,929: | Line 3,008: | ||
i += 2; |
i += 2; |
||
]; |
]; |
||
res</ |
res</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>{6,12,20,24,28,30,40,42,48,54,56,60,66,70,78,80,84,88,90,96,102,104,108,112,114,120,126,132,138,140,150,156,160,168,174,176,180,186,192,198,204,208,210,216,220,222,224,228,234,240,246,252,258,260,264,270,272,276,280,282,294,300,304,306,308,312,318,320,330,336,340,342,348,350,352,354,360,364,366,368,372,378,380,384,390,396,402,408,414,416,420,426,432,438,440,444,448,456,460,462,464,468,474,476,480,486,490,492,496,498,500,504,510,516,520,522,528,532,534,540,544,546,550,552,558,560,564,570,572,580,582,588,594,600,606,608,612,616,618,620,624,630,636,640,642,644,650,654,660,666,672,678,680,684,690,696,700,702,704,708,714,720,726,728,732,736,740,744,750,756,760,762,768,770,780,786,792,798,804,810,812,816,820,822,828,832,834,836,840,852,858,860,864,868,870,876,880,888,894,896,906,910,912,918,920,924,928,930,936,940,942,945,948,952,960,966,972,978,980,984} |
<pre>{6,12,20,24,28,30,40,42,48,54,56,60,66,70,78,80,84,88,90,96,102,104,108,112,114,120,126,132,138,140,150,156,160,168,174,176,180,186,192,198,204,208,210,216,220,222,224,228,234,240,246,252,258,260,264,270,272,276,280,282,294,300,304,306,308,312,318,320,330,336,340,342,348,350,352,354,360,364,366,368,372,378,380,384,390,396,402,408,414,416,420,426,432,438,440,444,448,456,460,462,464,468,474,476,480,486,490,492,496,498,500,504,510,516,520,522,528,532,534,540,544,546,550,552,558,560,564,570,572,580,582,588,594,600,606,608,612,616,618,620,624,630,636,640,642,644,650,654,660,666,672,678,680,684,690,696,700,702,704,708,714,720,726,728,732,736,740,744,750,756,760,762,768,770,780,786,792,798,804,810,812,816,820,822,828,832,834,836,840,852,858,860,864,868,870,876,880,888,894,896,906,910,912,918,920,924,928,930,936,940,942,945,948,952,960,966,972,978,980,984} |
||
Line 2,936: | Line 3,015: | ||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="Nim">import math, strutils |
||
template isEven(n: int): bool = (n and 1) == 0 |
template isEven(n: int): bool = (n and 1) == 0 |
||
Line 3,006: | Line 3,085: | ||
inc count |
inc count |
||
stdout.write if count mod 8 == 0: '\n' else: ' ' |
stdout.write if count mod 8 == 0: '\n' else: ' ' |
||
inc n, 2</ |
inc n, 2</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,034: | Line 3,113: | ||
960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 |
960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 |
||
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</pre> |
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</pre> |
||
=={{header|PARI/GP}}== |
|||
{{trans|Mathematica_/_Wolfram_Language}} |
|||
<syntaxhighlight lang="PARI/GP"> |
|||
\\ Define a function to check if a number is Zumkeller |
|||
isZumkeller(n) = { |
|||
my(d = divisors(n)); |
|||
my(ds = sum(i=1, #d, d[i])); \\ Total of divisors |
|||
if (ds % 2, return(0)); \\ If sum of divisors is odd, return false |
|||
my(coeffs = vector(ds+1, i, 0)); \\ Create a vector to store coefficients |
|||
coeffs[1] = 1; |
|||
for(i=1, #d, coeffs = Pol(coeffs) * (1 + x^d[i]); coeffs = Vecrev(coeffs); if(#coeffs > ds + 1, coeffs = coeffs[^1])); \\ Generate coefficients |
|||
coeffs[ds \ 2 + 1] > 0; \\ Check if the middle coefficient is positive |
|||
} |
|||
\\ Generate a list of Zumkeller numbers |
|||
ZumkellerList(limit) = { |
|||
my(res = List(), i = 1); |
|||
while(#res < limit, |
|||
if(isZumkeller(i), listput(res, i)); |
|||
i++; |
|||
); |
|||
Vec(res); \\ Convert list to vector |
|||
} |
|||
\\ Generate a list of odd Zumkeller numbers |
|||
OddZumkellerList(limit) = { |
|||
my(res = List(), i = 1); |
|||
while(#res < limit, |
|||
if(isZumkeller(i), listput(res, i)); |
|||
i += 2; \\ Only check odd numbers |
|||
); |
|||
Vec(res); \\ Convert list to vector |
|||
} |
|||
\\ Call the functions to get the lists |
|||
zumkeller220 = ZumkellerList(220); |
|||
oddZumkeller40 = OddZumkellerList(40); |
|||
\\ Print the results |
|||
print(zumkeller220); |
|||
print(oddZumkeller40); |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
[6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96, 102, 104, 108, 112, 114, 120, 126, 132, 138, 140, 150, 156, 160, 168, 174, 176, 180, 186, 192, 198, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252, 258, 260, 264, 270, 272, 276, 280, 282, 294, 300, 304, 306, 308, 312, 318, 320, 330, 336, 340, 342, 348, 350, 352, 354, 360, 364, 366, 368, 372, 378, 380, 384, 390, 396, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 456, 460, 462, 464, 468, 474, 476, 480, 486, 490, 492, 496, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552, 558, 560, 564, 570, 572, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 650, 654, 660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 740, 744, 750, 756, 760, 762, 768, 770, 780, 786, 792, 798, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 852, 858, 860, 864, 868, 870, 876, 880, 888, 894, 896, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 960, 966, 972, 978, 980, 984] |
|||
[945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305] |
|||
</pre> |
|||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
Using sieve for primedecomposition<BR> |
Using sieve for primedecomposition<BR> |
||
Now using the trick, that one partition sum must include n and improved recursive search.<BR> |
Now using the trick, that one partition sum must include n and improved recursive search.<BR> |
||
Limit is ~1.2e11 |
Limit is ~1.2e11 |
||
< |
<syntaxhighlight lang="pascal">program zumkeller; |
||
//https://oeis.org/A083206/a083206.txt |
//https://oeis.org/A083206/a083206.txt |
||
{$IFDEF FPC} |
{$IFDEF FPC} |
||
Line 3,728: | Line 3,857: | ||
writeln('runtime ',(GetTickCount64-T0)/1000:8:3,' s'); |
writeln('runtime ',(GetTickCount64-T0)/1000:8:3,' s'); |
||
END. |
END. |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,809: | Line 3,938: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{libheader|ntheory}} |
{{libheader|ntheory}} |
||
< |
<syntaxhighlight lang="perl">use strict; |
||
use warnings; |
use warnings; |
||
use feature 'say'; |
use feature 'say'; |
||
Line 3,853: | Line 3,982: | ||
$n = 0; $z = ''; |
$n = 0; $z = ''; |
||
$z .= do { $n < 40 ? (!!($_%2 and $_%5) and is_Zumkeller($_) and ++$n and "$_ ") : last } for 1 .. Inf; |
$z .= do { $n < 40 ? (!!($_%2 and $_%5) and is_Zumkeller($_) and ++$n and "$_ ") : last } for 1 .. Inf; |
||
in_columns(10, $z);</ |
in_columns(10, $z);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,883: | Line 4,012: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
<!-- |
<!--(phixonline)--> |
||
<syntaxhighlight lang="Phix"> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">isPartSum</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> |
|||
with javascript_semantics |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">true</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
function isPartSum(sequence f, integer l, t) |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
if t=0 then return true end if |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">[</span><span style="color: #000000;">l</span><span style="color: #0000FF;">]</span> |
|||
if l=0 then return false end if |
|||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">last</span> <span style="color: #008080;">and</span> <span style="color: #000000;">isPartSum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">-</span><span style="color: #000000;">last</span><span style="color: #0000FF;">))</span> |
|||
integer last = f[l] |
|||
<span style="color: #008080;">or</span> <span style="color: #000000;">isPartSum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> |
|||
return (t>=last and isPartSum(f, l-1, t-last)) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
or isPartSum(f, l-1, t) |
|||
end function |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">isZumkeller</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> |
|||
function isZumkeller(integer n) |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span> |
|||
sequence f = factors(n,1) |
|||
<span style="color: #000080;font-style:italic;">-- an odd sum cannot be split into two equal sums</span> |
|||
integer t = sum(f) |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
-- an odd sum cannot be split into two equal sums |
|||
<span style="color: #000080;font-style:italic;">-- if n is odd use 'abundant odd number' optimization</span> |
|||
if odd(t) then return false end if |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> |
|||
-- if n is odd use 'abundant odd number' optimization |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">abundance</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span> |
|||
if odd(n) then |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">abundance</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">abundance</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> |
|||
integer abundance := t - 2*n |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
return abundance>0 and even(abundance) |
|||
<span style="color: #000080;font-style:italic;">-- if n and t both even check for any partition of t/2</span> |
|||
end if |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">isPartSum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> |
|||
-- if n and t both even check for any partition of t/2 |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
return isPartSum(f, length(f), t/2) |
|||
end function |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">220</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d "</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">40</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%5d "</span><span style="color: #0000FF;">},</span> |
|||
sequence tests = {{220,1,0,20,"%3d %n"}, |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">40</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%7d "</span><span style="color: #0000FF;">}}</span> |
|||
{40,2,0,10,"%5d %n"}, |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">lim</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rem</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cr</span><span style="color: #0000FF;">;</span> <span style="color: #004080;">string</span> <span style="color: #000000;">fmt</span> |
|||
{40,2,5,8,"%7d %n"}} |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
integer lim, step, rem, cr; string fmt |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">lim</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rem</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fmt</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]</span> |
|||
for t=1 to length(tests) do |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">odd</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">step</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"odd "</span><span style="color: #0000FF;">),</span> |
|||
{lim, step, rem, cr, fmt} = tests[t] |
|||
<span style="color: #000000;">wch</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rem</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"which don't end in 5 "</span><span style="color: #0000FF;">)</span> |
|||
string o = iff(step=1?"":"odd "), |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The first %d %sZumkeller numbers %sare:\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">lim</span><span style="color: #0000FF;">,</span><span style="color: #000000;">odd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">wch</span><span style="color: #0000FF;">})</span> |
|||
w = iff(rem=0?"":"which don't end in 5 ") |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
printf(1,"The first %d %sZumkeller numbers %sare:\n",{lim,o,w}) |
|||
<span style="color: #008080;">while</span> <span style="color: #000000;">count</span><span style="color: #0000FF;"><</span><span style="color: #000000;">lim</span> <span style="color: #008080;">do</span> |
|||
integer i = step+1, count = 0 |
|||
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">rem</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">rem</span><span style="color: #0000FF;">)</span> |
|||
while count<lim do |
|||
<span style="color: #008080;">and</span> <span style="color: #000000;">isZumkeller</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
if (rem=0 or remainder(i,10)!=rem) |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
and isZumkeller(i) then |
|||
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
count += 1 |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cr</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
printf(1,fmt,{i,remainder(count,cr)=0}) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end if |
|||
<span style="color: #000000;">i</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">step</span> |
|||
i += step |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
end while |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span> |
|||
printf(1,"\n") |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<!--</lang>--> |
|||
</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,964: | Line 4,094: | ||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="PicoLisp">(de propdiv (N) |
||
(make |
(make |
||
(for I N |
(for I N |
||
Line 4,015: | Line 4,145: | ||
(and |
(and |
||
(=0 (% C 8)) |
(=0 (% C 8)) |
||
(prinl) ) ) )</ |
(prinl) ) ) )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,046: | Line 4,176: | ||
===Procedural=== |
===Procedural=== |
||
Modified from a footnote at OEIS A083207 (see reference in problem text) by Charles R Greathouse IV. |
Modified from a footnote at OEIS A083207 (see reference in problem text) by Charles R Greathouse IV. |
||
< |
<syntaxhighlight lang="python">from sympy import divisors |
||
from sympy.combinatorics.subsets import Subset |
from sympy.combinatorics.subsets import Subset |
||
Line 4,078: | Line 4,208: | ||
print("\n\n40 odd Zumkeller numbers:") |
print("\n\n40 odd Zumkeller numbers:") |
||
printZumkellers(40, True) |
printZumkellers(40, True) |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
220 Zumkeller numbers: |
220 Zumkeller numbers: |
||
Line 4,116: | Line 4,246: | ||
Relying on the standard Python libraries, as an alternative to importing SymPy: |
Relying on the standard Python libraries, as an alternative to importing SymPy: |
||
< |
<syntaxhighlight lang="python">'''Zumkeller numbers''' |
||
from itertools import ( |
from itertools import ( |
||
Line 4,318: | Line 4,448: | ||
# MAIN --- |
# MAIN --- |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
main()</ |
main()</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>First 220 Zumkeller numbers: |
<pre>First 220 Zumkeller numbers: |
||
Line 4,355: | Line 4,485: | ||
{{trans|Zkl}} |
{{trans|Zkl}} |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(require math/number-theory) |
(require math/number-theory) |
||
Line 4,395: | Line 4,525: | ||
(newline) |
(newline) |
||
(tabulate "First 40 odd Zumkeller numbers not ending in 5:" |
(tabulate "First 40 odd Zumkeller numbers not ending in 5:" |
||
(first-n-matching-naturals 40 (λ (n) (and (odd? n) (not (= 5 (modulo n 10))) (zum? n)))))</ |
(first-n-matching-naturals 40 (λ (n) (and (odd? n) (not (= 5 (modulo n 10))) (zum? n)))))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 4,419: | Line 4,549: | ||
(formerly Perl 6) |
(formerly Perl 6) |
||
{{libheader|ntheory}} |
{{libheader|ntheory}} |
||
<lang |
<syntaxhighlight lang="raku" line>use ntheory:from<Perl5> <factor is_prime>; |
||
sub zumkeller ($range) { |
sub zumkeller ($range) { |
||
Line 4,449: | Line 4,579: | ||
# Stretch. Slow to calculate. (minutes) |
# Stretch. Slow to calculate. (minutes) |
||
put "\nFirst 40 odd Zumkeller numbers not divisible by 5:\n" ~ |
put "\nFirst 40 odd Zumkeller numbers not divisible by 5:\n" ~ |
||
zumkeller(flat (^Inf).map: {my \p = 10 * $_; p+1, p+3, p+7, p+9} )[^40].rotor(10)».fmt('%7d').join: "\n";</ |
zumkeller(flat (^Inf).map: {my \p = 10 * $_; p+1, p+3, p+7, p+9} )[^40].rotor(10)».fmt('%7d').join: "\n";</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>First 220 Zumkeller numbers: |
<pre>First 220 Zumkeller numbers: |
||
Line 4,478: | Line 4,608: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
The construction of the partitions were created in the order in which the most likely partitions would match. |
The construction of the partitions were created in the order in which the most likely partitions would match. |
||
< |
<syntaxhighlight lang="rexx">/*REXX pgm finds & shows Zumkeller numbers: 1st N; 1st odd M; 1st odd V not ending in 5.*/ |
||
parse arg n m v . /*obtain optional arguments from the CL*/ |
parse arg n m v . /*obtain optional arguments from the CL*/ |
||
if n=='' | n=="," then n= 220 /*Not specified? Then use the default.*/ |
if n=='' | n=="," then n= 220 /*Not specified? Then use the default.*/ |
||
Line 4,568: | Line 4,698: | ||
if p1==p2 then return 1 /*Partition sums equal? Then X is Zum.*/ |
if p1==p2 then return 1 /*Partition sums equal? Then X is Zum.*/ |
||
end /*part*/ |
end /*part*/ |
||
return 0 /*no partition sum passed. X isn't Zum*/</ |
return 0 /*no partition sum passed. X isn't Zum*/</syntaxhighlight> |
||
{{out|output|text= when using the default inputs:}} |
{{out|output|text= when using the default inputs:}} |
||
<pre> |
<pre> |
||
Line 4,591: | Line 4,721: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
load "stdlib.ring" |
load "stdlib.ring" |
||
Line 4,756: | Line 4,886: | ||
last -= 1 |
last -= 1 |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 4,782: | Line 4,912: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">class Integer |
||
def divisors |
def divisors |
||
Line 4,818: | Line 4,948: | ||
puts "\n#{n=40} odd Zumkeller numbers not ending with 5:" |
puts "\n#{n=40} odd Zumkeller numbers not ending with 5:" |
||
p_enum 1.step(by: 2).lazy.select{|x| x % 5 > 0 && x.zumkeller?}.take(n) |
p_enum 1.step(by: 2).lazy.select{|x| x % 5 > 0 && x.zumkeller?}.take(n) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>220 Zumkeller numbers: |
<pre>220 Zumkeller numbers: |
||
Line 4,852: | Line 4,982: | ||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
< |
<syntaxhighlight lang="rust"> |
||
use std::convert::TryInto; |
use std::convert::TryInto; |
||
Line 4,937: | Line 5,067: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,955: | Line 5,085: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">func is_Zumkeller(n) { |
||
return false if n.is_prime |
return false if n.is_prime |
||
Line 4,988: | Line 5,118: | ||
say "\nFirst 40 odd Zumkeller numbers not divisible by 5: " |
say "\nFirst 40 odd Zumkeller numbers not divisible by 5: " |
||
say (1..Inf `by` 2 -> lazy.grep { _ % 5 != 0 }.grep(is_Zumkeller).first(40).join(' '))</ |
say (1..Inf `by` 2 -> lazy.grep { _ % 5 != 0 }.grep(is_Zumkeller).first(40).join(' '))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,002: | Line 5,132: | ||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
< |
<syntaxhighlight lang="Standard ML"> |
||
exception Found of string ; |
exception Found of string ; |
||
Line 5,055: | Line 5,185: | ||
end; |
end; |
||
</syntaxhighlight> |
|||
</lang> |
|||
call loop and output - interpreter |
call loop and output - interpreter |
||
< |
<syntaxhighlight lang="Standard ML"> |
||
- val Zumkellerlist = fn step => fn no5 => |
- val Zumkellerlist = fn step => fn no5 => |
||
let |
let |
||
Line 5,090: | Line 5,220: | ||
742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, |
742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, |
||
1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377 |
1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
Line 5,096: | Line 5,226: | ||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="swift">import Foundation |
||
extension BinaryInteger { |
extension BinaryInteger { |
||
Line 5,156: | Line 5,286: | ||
print("First 220 zumkeller numbers are \(Array(zums.prefix(220)))") |
print("First 220 zumkeller numbers are \(Array(zums.prefix(220)))") |
||
print("First 40 odd zumkeller numbers are \(Array(oddZums.prefix(40)))") |
print("First 40 odd zumkeller numbers are \(Array(oddZums.prefix(40)))") |
||
print("First 40 odd zumkeller numbers that don't end in a 5 are: \(Array(oddZumsWithout5.prefix(40)))")</ |
print("First 40 odd zumkeller numbers that don't end in a 5 are: \(Array(oddZumsWithout5.prefix(40)))")</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 5,163: | Line 5,293: | ||
First 40 odd zumkeller numbers are: [945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305] |
First 40 odd zumkeller numbers are: [945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305] |
||
First 40 odd zumkeller numbers that don't end in a 5 are: [81081, 153153, 171171, 189189, 207207, 223839, 243243, 261261, 279279, 297297, 351351, 459459, 513513, 567567, 621621, 671517, 729729, 742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, 1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377]</pre> |
First 40 odd zumkeller numbers that don't end in a 5 are: [81081, 153153, 171171, 189189, 207207, 223839, 243243, 261261, 279279, 297297, 351351, 459459, 513513, 567567, 621621, 671517, 729729, 742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, 1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377]</pre> |
||
=={{header|Typescript}}== |
|||
{{trans|Go}} |
|||
<syntaxhighlight lang="typescript"> |
|||
/** |
|||
* return an array of divisors of a number(n) |
|||
* @params {number} n The number to find divisors from |
|||
* @return {number[]} divisors of n |
|||
*/ |
|||
function getDivisors(n: number): number[] { |
|||
//initialize divisors array |
|||
let divisors: number[] = [1, n] |
|||
//loop through all numbers from 2 to sqrt(n) |
|||
for (let i = 2; i*i <= n; i++) { |
|||
// if i is a divisor of n |
|||
if (n % i == 0) { |
|||
// add i to divisors array |
|||
divisors.push(i); |
|||
// quotient of n/i is also a divisor of n |
|||
let j = n/i; |
|||
// if quotient is not equal to i |
|||
if (i != j) { |
|||
// add quotient to divisors array |
|||
divisors.push(j); |
|||
} |
|||
} |
|||
} |
|||
return divisors |
|||
} |
|||
/** |
|||
* return sum of an array of number |
|||
* @param {number[]} arr The array we need to sum |
|||
* @return {number} sum of arr |
|||
*/ |
|||
function getSum(arr: number[]): number { |
|||
return arr.reduce((prev, curr) => prev + curr, 0) |
|||
} |
|||
/** |
|||
* check if there is a subset of divisors which sums to a specific number |
|||
* @param {number[]} divs The array of divisors |
|||
* @param {number} sum The number to check if there's a subset of divisors which sums to it |
|||
* @return {boolean} true if sum is 0, false if divisors length is 0 |
|||
*/ |
|||
function isPartSum(divs: number[], sum: number): boolean { |
|||
// if sum is 0, the partition is sum up to the number(sum) |
|||
if (sum == 0) return true; |
|||
//get length of divisors array |
|||
let len = divs.length; |
|||
// if divisors array is empty the partion doesnt not sum up to the number(sum) |
|||
if (len == 0) return false; |
|||
//get last element of divisors array |
|||
let last = divs[len - 1]; |
|||
//create a copy of divisors array without the last element |
|||
const newDivs = [...divs]; |
|||
newDivs.pop(); |
|||
// if last element is greater than sum |
|||
if (last > sum) { |
|||
// recursively check if there's a subset of divisors which sums to sum using the new divisors array |
|||
return isPartSum(newDivs, sum); |
|||
} |
|||
// recursively check if there's a subset of divisors which sums to sum using the new divisors array |
|||
// or if there's a subset of divisors which sums to sum - last using the new divisors array |
|||
return isPartSum(newDivs, sum) || isPartSum(newDivs, sum - last); |
|||
} |
|||
/** |
|||
* check if a number is a Zumkeller number |
|||
* @param {number} n The number to check if it's a Zumkeller number |
|||
* @returns {boolean} true if n is a Zumkeller number, false otherwise |
|||
*/ |
|||
function isZumkeller(n: number): boolean { |
|||
// get divisors of n |
|||
let divs = getDivisors(n); |
|||
// get sum of divisors of n |
|||
let sum = getSum(divs); |
|||
// if sum is odd can't be split into two partitions with equal sums |
|||
if (sum % 2 == 1) return false; |
|||
// if n is odd use 'abundant odd number' optimization |
|||
if (n % 2 == 1) { |
|||
let abundance = sum - 2 * n |
|||
return abundance > 0 && abundance%2 == 0; |
|||
} |
|||
// if n and sum are both even check if there's a partition which totals sum / 2 |
|||
return isPartSum(divs, sum/2); |
|||
} |
|||
/** |
|||
* find x zumkeller numbers |
|||
* @param {number} x The number of zumkeller numbers to find |
|||
* @returns {number[]} array of x zumkeller numbers |
|||
*/ |
|||
function getXZumkelers(x: number): number[] { |
|||
let zumkellers: number[] = []; |
|||
let i = 2; |
|||
let count= 0; |
|||
while (count < x) { |
|||
if (isZumkeller(i)) { |
|||
zumkellers.push(i); |
|||
count++; |
|||
} |
|||
i++; |
|||
} |
|||
return zumkellers; |
|||
} |
|||
/** |
|||
* find x Odd Zumkeller numbers |
|||
* @param {number} x The number of odd zumkeller numbers to find |
|||
* @returns {number[]} array of x odd zumkeller numbers |
|||
*/ |
|||
function getXOddZumkelers(x: number): number[] { |
|||
let oddZumkellers: number[] = []; |
|||
let i = 3; |
|||
let count = 0; |
|||
while (count < x) { |
|||
if (isZumkeller(i)) { |
|||
oddZumkellers.push(i); |
|||
count++; |
|||
} |
|||
i += 2; |
|||
} |
|||
return oddZumkellers; |
|||
} |
|||
/** |
|||
* find x odd zumkeller number which are not end with 5 |
|||
* @param {number} x The number of odd zumkeller numbers to find |
|||
* @returns {number[]} array of x odd zumkeller numbers |
|||
*/ |
|||
function getXOddZumkellersNotEndWith5(x: number): number[] { |
|||
let oddZumkellers: number[] = []; |
|||
let i = 3; |
|||
let count = 0; |
|||
while (count < x) { |
|||
if (isZumkeller(i) && i % 10 != 5) { |
|||
oddZumkellers.push(i); |
|||
count++; |
|||
} |
|||
i += 2; |
|||
} |
|||
return oddZumkellers; |
|||
} |
|||
//get the first 220 zumkeller numbers |
|||
console.log("First 220 Zumkeller numbers: ", getXZumkelers(220)); |
|||
//get the first 40 odd zumkeller numbers |
|||
console.log("First 40 odd Zumkeller numbers: ", getXOddZumkelers(40)); |
|||
//get the first 40 odd zumkeller numbers which are not end with 5 |
|||
console.log("First 40 odd Zumkeller numbers which are not end with 5: ", getXOddZumkellersNotEndWith5(40)); |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
"First 220 Zumkeller numbers: ", [6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96, 102, 104, 108, 112, 114, 120, 126, 132, 138, 140, 150, 156, 160, 168, 174, 176, 180, 186, 192, 198, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252, 258, 260, 264, 270, 272, 276, 280, 282, 294, 300, 304, 306, 308, 312, 318, 320, 330, 336, 340, 342, 348, 350, 352, 354, 360, 364, 366, 368, 372, 378, 380, 384, 390, 396, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 456, 460, 462, 464, 468, 474, 476, 480, 486, 490, 492, 496, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552, 558, 560, 564, 570, 572, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 650, 654, 660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 740, 744, 750, 756, 760, 762, 768, 770, 780, 786, 792, 798, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 852, 858, 860, 864, 868, 870, 876, 880, 888, 894, 896, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 960, 966, 972, 978, 980, 984] |
|||
"First 40 odd Zumkeller numbers: ", [945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305] |
|||
"First 40 odd Zumkeller numbers which are not end with 5: ", [81081, 153153, 171171, 189189, 207207, 223839, 243243, 261261, 279279, 297297, 351351, 459459, 513513, 567567, 621621, 671517, 729729, 742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, 1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377] |
|||
</pre> |
|||
=={{header|Visual Basic .NET}}== |
=={{header|Visual Basic .NET}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="vbnet">Module Module1 |
||
Function GetDivisors(n As Integer) As List(Of Integer) |
Function GetDivisors(n As Integer) As List(Of Integer) |
||
Dim divs As New List(Of Integer) From { |
Dim divs As New List(Of Integer) From { |
||
Line 5,265: | Line 5,561: | ||
End While |
End While |
||
End Sub |
End Sub |
||
End Module</ |
End Module</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The first 220 Zumkeller numbers are: |
<pre>The first 220 Zumkeller numbers are: |
||
Line 5,293: | Line 5,589: | ||
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</pre> |
1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377</pre> |
||
=={{header|Vlang}}== |
=={{header|V (Vlang)}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
<lang vlang>fn get_divisors(n int) []int { |
<syntaxhighlight lang="v (vlang)">fn get_divisors(n int) []int { |
||
mut divs := [1, n] |
mut divs := [1, n] |
||
for i := 2; i*i <= n; i++ { |
for i := 2; i*i <= n; i++ { |
||
Line 5,382: | Line 5,678: | ||
} |
} |
||
println('') |
println('') |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 5,418: | Line 5,714: | ||
{{libheader|Wren-fmt}} |
{{libheader|Wren-fmt}} |
||
I've reversed the order of the recursive calls in the last line of the ''isPartSum'' function which, as noted in the Phix entry, seems to make little difference to Go but (as one might have expected) speeds up this Wren script enormously. The first part is now near instant but was taking several minutes previously. Overall it's now only about 5.5 times slower than Go itself which is a good result for the Wren interpreter. |
I've reversed the order of the recursive calls in the last line of the ''isPartSum'' function which, as noted in the Phix entry, seems to make little difference to Go but (as one might have expected) speeds up this Wren script enormously. The first part is now near instant but was taking several minutes previously. Overall it's now only about 5.5 times slower than Go itself which is a good result for the Wren interpreter. |
||
< |
<syntaxhighlight lang="wren">import "./math" for Int, Nums |
||
import "/fmt" for Fmt |
import "./fmt" for Fmt |
||
import "io" for Stdout |
import "io" for Stdout |
||
Line 5,484: | Line 5,780: | ||
i = i + 2 |
i = i + 2 |
||
} |
} |
||
System.print()</ |
System.print()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 5,517: | Line 5,813: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
{{trans|Julia}} {{trans|Go}} |
{{trans|Julia}} {{trans|Go}} |
||
< |
<syntaxhighlight lang="zkl">fcn properDivs(n){ // does not include n |
||
// if(n==1) return(T); // we con't care about this case |
// if(n==1) return(T); // we con't care about this case |
||
( pd:=[1..(n).toFloat().sqrt()].filter('wrap(x){ n%x==0 }) ) |
( pd:=[1..(n).toFloat().sqrt()].filter('wrap(x){ n%x==0 }) ) |
||
Line 5,540: | Line 5,836: | ||
} |
} |
||
canSum(sum/2,ds) and n or Void.Skip // sum is even |
canSum(sum/2,ds) and n or Void.Skip // sum is even |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="zkl">println("First 220 Zumkeller numbers:"); |
||
zw:=[2..].tweak(isZumkellerW); |
zw:=[2..].tweak(isZumkellerW); |
||
do(11){ zw.walk(20).pump(String,"%4d ".fmt).println() } |
do(11){ zw.walk(20).pump(String,"%4d ".fmt).println() } |
||
Line 5,551: | Line 5,847: | ||
println("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:"); |
println("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:"); |
||
zw:=[3..*, 2].tweak(fcn(n){ if(n%5) isZumkellerW(n) else Void.Skip }); |
zw:=[3..*, 2].tweak(fcn(n){ if(n%5) isZumkellerW(n) else Void.Skip }); |
||
do(5){ zw.walk(8).pump(String,"%7d ".fmt).println() }</ |
do(5){ zw.walk(8).pump(String,"%7d ".fmt).println() }</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre style="font-size:83%"> |
<pre style="font-size:83%"> |
Latest revision as of 23:28, 22 July 2024
You are encouraged to solve this task according to the task description, using any language you may know.
Zumkeller numbers are the set of numbers whose divisors can be partitioned into two disjoint sets that sum to the same value. Each sum must contain divisor values that are not in the other sum, and all of the divisors must be in one or the other. There are no restrictions on how the divisors are partitioned, only that the two partition sums are equal.
- E.G.
- 6 is a Zumkeller number; The divisors {1 2 3 6} can be partitioned into two groups {1 2 3} and {6} that both sum to 6.
- 10 is not a Zumkeller number; The divisors {1 2 5 10} can not be partitioned into two groups in any way that will both sum to the same value.
- 12 is a Zumkeller number; The divisors {1 2 3 4 6 12} can be partitioned into two groups {1 3 4 6} and {2 12} that both sum to 14.
Even Zumkeller numbers are common; odd Zumkeller numbers are much less so. For values below 10^6, there is at least one Zumkeller number in every 12 consecutive integers, and the vast majority of them are even. The odd Zumkeller numbers are very similar to the list from the task Abundant odd numbers; they are nearly the same except for the further restriction that the abundance (A(n) = sigma(n) - 2n), must be even: A(n) mod 2 == 0
- Task
-
- Write a routine (function, procedure, whatever) to find Zumkeller numbers.
- Use the routine to find and display here, on this page, the first 220 Zumkeller numbers.
- Use the routine to find and display here, on this page, the first 40 odd Zumkeller numbers.
- Optional, stretch goal: Use the routine to find and display here, on this page, the first 40 odd Zumkeller numbers that don't end with 5.
- See Also
- OEIS:A083207 - Zumkeller numbers to get an impression of different partitions OEIS:A083206 Zumkeller partitions
- OEIS:A174865 - Odd Zumkeller numbers
- Related Tasks
11l
F getDivisors(n)
V divs = [1, n]
V i = 2
L i * i <= n
I n % i == 0
divs [+]= i
V j = n I/ i
I i != j
divs [+]= j
i++
R divs
F isPartSum(divs, sum)
I sum == 0
R 1B
V le = divs.len
I le == 0
R 0B
V last = divs.last
[Int] newDivs
L(i) 0 .< le - 1
newDivs [+]= divs[i]
I last > sum
R isPartSum(newDivs, sum)
E
R isPartSum(newDivs, sum) | isPartSum(newDivs, sum - last)
F isZumkeller(n)
V divs = getDivisors(n)
V s = sum(divs)
I s % 2 == 1
R 0B
I n % 2 == 1
V abundance = s - 2 * n
R abundance > 0 & abundance % 2 == 0
R isPartSum(divs, s I/ 2)
print(‘The first 220 Zumkeller numbers are:’)
V i = 2
V count = 0
L count < 220
I isZumkeller(i)
print(‘#3 ’.format(i), end' ‘’)
count++
I count % 20 == 0
print()
i++
print("\nThe first 40 odd Zumkeller numbers are:")
i = 3
count = 0
L count < 40
I isZumkeller(i)
print(‘#5 ’.format(i), end' ‘’)
count++
I count % 10 == 0
print()
i += 2
print("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:")
i = 3
count = 0
L count < 40
I i % 10 != 5 & isZumkeller(i)
print(‘#7 ’.format(i), end' ‘’)
count++
I count % 8 == 0
print()
i += 2
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
AArch64 Assembly
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program zumkellex641.s */
/* REMARK 1 : this program use routines in a include file
see task Include a file language arm assembly
for the routine affichageMess conversion10
see at end of this program the instruction include */
/* REMARK 2 : this program is not optimized.
Not search First 40 odd Zumkeller numbers not divisible by 5 */
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ NBDIVISORS, 100
/*******************************************/
/* Structures */
/********************************************/
/* structurea area divisors */
.struct 0
div_ident: // ident
.struct div_ident + 8
div_flag: // value 0, 1 or 2
.struct div_flag + 8
div_fin:
/*******************************************/
/* Initialized data */
/*******************************************/
.data
szMessStartPgm: .asciz "Program start \n"
szMessEndPgm: .asciz "Program normal end.\n"
szMessErrorArea: .asciz "\033[31mError : area divisors too small.\n"
szMessError: .asciz "\033[31mError !!!\n"
szCarriageReturn: .asciz "\n"
/* datas message display */
szMessEntete: .asciz "The first 220 Zumkeller numbers are:\n"
sNumber: .space 4*20,' '
.space 12,' ' // for end of conversion
szMessListDivi: .asciz "Divisors list : \n"
szMessListDiviHeap: .asciz "Heap 1 Divisors list : \n"
szMessResult: .ascii " "
sValue: .space 12,' '
.asciz ""
szMessEntete1: .asciz "The first 40 odd Zumkeller numbers are:\n"
/*******************************************/
/* UnInitialized data */
/*******************************************/
.bss
.align 4
tbDivisors: .skip div_fin * NBDIVISORS // area divisors
sZoneConv: .skip 30
/*******************************************/
/* code section */
/*******************************************/
.text
.global main
main: // program start
ldr x0,qAdrszMessStartPgm // display start message
bl affichageMess
ldr x0,qAdrszMessEntete // display message
bl affichageMess
mov x2,#1 // counter number
mov x3,#0 // counter zumkeller number
mov x4,#0 // counter for line display
1:
mov x0,x2 // number
mov x1,#0 // display flag
bl testZumkeller
cmp x0,#1 // zumkeller ?
bne 3f // no
mov x0,x2
ldr x1,qAdrsZoneConv // and convert ascii string
bl conversion10
ldr x0,qAdrsZoneConv // copy result in display line
ldr x1,qAdrsNumber
lsl x5,x4,#2
add x1,x1,x5
11:
ldrb w5,[x0],1
cbz w5,12f
strb w5,[x1],1
b 11b
12:
add x4,x4,#1
cmp x4,#20
blt 2f
//add x1,x1,#3 // carriage return at end of display line
mov x0,#'\n'
strb w0,[x1]
mov x0,#0
strb w0,[x1,#1] // end of display line
ldr x0,qAdrsNumber // display result message
bl affichageMess
mov x4,#0
2:
add x3,x3,#1 // increment counter
3:
add x2,x2,#1 // increment number
cmp x3,#220 // end ?
blt 1b
/* raz display line */
ldr x0,qAdrsNumber
mov x1,' '
mov x2,0
31:
strb w1,[x0,x2]
add x2,x2,1
cmp x2,4*20
blt 31b
/* odd zumkeller numbers */
ldr x0,qAdrszMessEntete1
bl affichageMess
mov x2,#1
mov x3,#0
mov x4,#0
4:
mov x0,x2 // number
mov x1,#0 // display flag
bl testZumkeller
cmp x0,#1
bne 6f
mov x0,x2
ldr x1,qAdrsZoneConv // and convert ascii string
bl conversion10
ldr x0,qAdrsZoneConv // copy result in display line
ldr x1,qAdrsNumber
lsl x5,x4,#3
add x1,x1,x5
41:
ldrb w5,[x0],1
cbz w5,42f
strb w5,[x1],1
b 41b
42:
add x4,x4,#1
cmp x4,#8
blt 5f
mov x0,#'\n'
strb w0,[x1]
strb wzr,[x1,#1]
ldr x0,qAdrsNumber // display result message
bl affichageMess
mov x4,#0
5:
add x3,x3,#1
6:
add x2,x2,#2
cmp x3,#40
blt 4b
ldr x0,qAdrszMessEndPgm // display end message
bl affichageMess
b 100f
99: // display error message
ldr x0,qAdrszMessError
bl affichageMess
100: // standard end of the program
mov x0, #0 // return code
mov x8, #EXIT // request to exit program
svc 0 // perform system call
qAdrszMessStartPgm: .quad szMessStartPgm
qAdrszMessEndPgm: .quad szMessEndPgm
qAdrszMessError: .quad szMessError
qAdrszCarriageReturn: .quad szCarriageReturn
qAdrszMessResult: .quad szMessResult
qAdrsValue: .quad sValue
qAdrszMessEntete: .quad szMessEntete
qAdrszMessEntete1: .quad szMessEntete1
qAdrsNumber: .quad sNumber
qAdrsZoneConv: .quad sZoneConv
/******************************************************************/
/* test if number is Zumkeller number */
/******************************************************************/
/* x0 contains the number */
/* x1 contains display flag (<>0: display, 0: no display ) */
/* x0 return 1 if Zumkeller number else return 0 */
testZumkeller:
stp x1,lr,[sp,-16]! // save registers
stp x2,x3,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
stp x6,x7,[sp,-16]! // save registers
mov x7,x1 // save flag
ldr x1,qAdrtbDivisors
bl divisors // create area of divisors
cmp x0,#0 // 0 divisors or error ?
ble 98f
mov x5,x0 // number of dividers
mov x6,x1 // number of odd dividers
cmp x7,#1 // display divisors ?
bne 1f
ldr x0,qAdrszMessListDivi // yes
bl affichageMess
mov x0,x5
mov x1,#0
ldr x2,qAdrtbDivisors
bl printHeap
1:
tst x6,#1 // number of odd divisors is odd ?
bne 99f
mov x0,x5
mov x1,#0
ldr x2,qAdrtbDivisors
bl sumDivisors // compute divisors sum
tst x0,#1 // sum is odd ?
bne 99f // yes -> end
lsr x6,x0,#1 // compute sum /2
mov x0,x6 // x0 contains sum / 2
mov x1,#1 // first heap
mov x3,x5 // number divisors
mov x4,#0 // N° element to start
bl searchHeap
cmp x0,#-2
beq 100f // end
cmp x0,#-1
beq 100f // end
cmp x7,#1 // print flag ?
bne 2f
ldr x0,qAdrszMessListDiviHeap
bl affichageMess
mov x0,x5 // yes print divisors of first heap
ldr x2,qAdrtbDivisors
mov x1,#1
bl printHeap
2:
mov x0,#1 // ok
b 100f
98:
mov x0,-1
b 100f
99:
mov x0,#0
b 100f
100:
ldp x6,x7,[sp],16 // restaur 2 registers
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x2,x3,[sp],16 // restaur 2 registers
ldp x1,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
qAdrtbDivisors: .quad tbDivisors
qAdrszMessListDiviHeap: .quad szMessListDiviHeap
/******************************************************************/
/* search sum divisors = sum / 2 */
/******************************************************************/
/* x0 contains sum to search */
/* x1 contains flag (1 or 2) */
/* x2 contains address of divisors area */
/* x3 contains elements number */
/* x4 contains N° element to start */
/* x0 return -2 end search */
/* x0 return -1 no heap */
/* x0 return 0 Ok */
/* recursive routine */
searchHeap:
stp x3,lr,[sp,-16]! // save registers
stp x4,x5,[sp,-16]! // save registers
stp x6,x8,[sp,-16]! // save registers
1:
cmp x4,x3 // indice = elements number
beq 99f
lsl x6,x4,#4 // compute element address
add x6,x6,x2
ldr x7,[x6,#div_flag] // flag equal ?
cmp x7,#0
bne 6f
ldr x5,[x6,#div_ident]
cmp x5,x0 // element value = remaining amount
beq 7f // yes
bgt 6f // too large
// too less
mov x8,x0 // save sum
sub x0,x0,x5 // new sum to find
add x4,x4,#1 // next divisors
bl searchHeap // other search
cmp x0,#0 // find -> ok
beq 5f
mov x0,x8 // sum begin
sub x4,x4,#1 // prev divisors
bl razFlags // zero in all flags > current element
4:
add x4,x4,#1 // last divisors
b 1b
5:
str x1,[x6,#div_flag] // flag -> area element flag
b 100f
6:
add x4,x4,#1 // last divisors
b 1b
7:
str x1,[x6,#div_flag] // flag -> area element flag
mov x0,#0 // search ok
b 100f
8:
mov x0,#-1 // end search
b 100f
99:
mov x0,#-2
b 100f
100:
ldp x6,x8,[sp],16 // restaur 2 registers
ldp x4,x5,[sp],16 // restaur 2 registers
ldp x3,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/******************************************************************/
/* raz flags */
/******************************************************************/
/* x0 contains sum to search */
/* x1 contains flag (1 or 2) */
/* x2 contains address of divisors area */
/* x3 contains elements number */
/* x4 contains N° element to start */
/* x5 contains current sum */
/* REMARK : NO SAVE REGISTERS x14 x15 x16 AND LR */
razFlags:
mov x14,x4
1:
cmp x14,x3 // indice > nb elements ?
bge 100f // yes -> end
lsl x15,x14,#4
add x15,x15,x2 // compute address element
ldr x16,[x15,#div_flag] // load flag
cmp x1,x16 // equal ?
bne 2f
str xzr,[x15,#div_flag] // yes -> store 0
2:
add x14,x14,#1 // increment indice
b 1b // and loop
100:
ret // return to address lr x30
/******************************************************************/
/* compute sum of divisors */
/******************************************************************/
/* x0 contains elements number */
/* x1 contains flag (0 1 or 2)
/* x2 contains address of divisors area
/* x0 return divisors sum */
/* REMARK : NO SAVE REGISTERS x13 x14 x15 x16 AND LR */
sumDivisors:
mov x13,#0 // indice
mov x16,#0 // sum
1:
lsl x14,x13,#4 // N° element * 16
add x14,x14,x2
ldr x15,[x14,#div_flag] // compare flag
cmp x15,x1
bne 2f
ldr x15,[x14,#div_ident] // load value
add x16,x16,x15 // and add
2:
add x13,x13,#1
cmp x13,x0
blt 1b
mov x0,x16 // return sum
100:
ret // return to address lr x30
/******************************************************************/
/* print heap */
/******************************************************************/
/* x0 contains elements number */
/* x1 contains flag (0 1 or 2) */
/* x2 contains address of divisors area */
printHeap:
stp x2,lr,[sp,-16]! // save registers
stp x3,x4,[sp,-16]! // save registers
stp x5,x6,[sp,-16]! // save registers
stp x1,x7,[sp,-16]! // save registers
mov x6,x0
mov x5,x1
mov x3,#0 // indice
1:
lsl x1,x3,#4 // N° element * 16
add x1,x1,x2
ldr x4,[x1,#div_flag]
cmp x4,x5
bne 2f
ldr x0,[x1,#div_ident]
ldr x1,qAdrsValue // and convert ascii string
bl conversion10
ldr x0,qAdrszMessResult // display result message
bl affichageMess
2:
add x3,x3,#1
cmp x3,x6
blt 1b
ldr x0,qAdrszCarriageReturn
bl affichageMess
100:
ldp x1,x8,[sp],16 // restaur 2 registers
ldp x5,x6,[sp],16 // restaur 2 registers
ldp x3,x4,[sp],16 // restaur 2 registers
ldp x2,lr,[sp],16 // restaur 2 registers
ret // return to address lr x30
/******************************************************************/
/* divisors function */
/******************************************************************/
/* x0 contains the number */
/* x1 contains address of divisors area
/* x0 return divisors number */
/* x1 return counter odd divisors */
/* REMARK : NO SAVE REGISTERS x10 x11 x12 x13 x14 x15 x16 x17 x18 */
divisors:
str lr,[sp,-16]! // save register LR
cmp x0,#1 // = 1 ?
ble 98f
mov x17,x0
mov x18,x1
mov x11,#1 // counter odd divisors
mov x0,#1 // first divisor = 1
str x0,[x18,#div_ident]
mov x0,#0
str x0,[x18,#div_flag]
tst x17,#1 // number is odd ?
cinc x11,x11,ne // count odd divisors
mov x0,x17 // last divisor = N
add x10,x18,#16 // store at next element
str x0,[x10,#div_ident]
mov x0,#0
str x0,[x10,#div_flag]
mov x16,#2 // first divisor
mov x15,#2 // Counter divisors
2: // begin loop
udiv x12,x17,x16
msub x13,x12,x16,x17
cmp x13,#0 // remainder = 0 ?
bne 3f
cmp x12,x16
blt 4f // quot<divisor end
lsl x10,x15,#4 // N° element * 16
add x10,x10,x18 // and add at area begin address
str x12,[x10,#div_ident]
str xzr,[x10,#div_flag]
add x15,x15,#1 // increment counter
cmp x15,#NBDIVISORS // area maxi ?
bge 99f
tst x12,#1
cinc x11,x11,ne // count odd divisors
cmp x12,x16 // quotient = divisor ?
ble 4f
lsl x10,x15,#4 // N° element * 16
add x10,x10,x18 // and add at area begin address
str x16,[x10,#div_ident]
str xzr,[x10,#div_flag]
add x15,x15,#1 // increment counter
cmp x15,#NBDIVISORS // area maxi ?
bge 99f
tst x16,#1
cinc x11,x11,ne // count odd divisors
3:
cmp x12,x16
ble 4f
add x16,x16,#1 // increment divisor
b 2b // and loop
4:
mov x0,x15 // return divisors number
mov x1,x11 // return count odd divisors
b 100f
98:
mov x0,0
b 100f
99: // error
ldr x0,qAdrszMessErrorArea
bl affichageMess
mov x0,-1
100:
ldr lr,[sp],16 // restaur 1 registers
ret // return to address lr x30
qAdrszMessListDivi: .quad szMessListDivi
qAdrszMessErrorArea: .quad szMessErrorArea
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
Program start The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 Program normal end.
AppleScript
On my machine, this takes about 0.28 seconds to perform the two main searches and a further 107 to do the stretch task. However, the latter time can be dramatically reduced to 1.7 seconds with the cheat of knowing beforehand that the first 200 or so odd Zumkellers not ending with 5 are divisible by 63. The "abundant number" optimisation's now used with odd numbers, but the cheat-free running time was only two to three seconds longer without it.
-- Sum n's proper divisors.
on aliquotSum(n)
if (n < 2) then return 0
set sum to 1
set sqrt to n ^ 0.5
set limit to sqrt div 1
if (limit = sqrt) then
set sum to sum + limit
set limit to limit - 1
end if
repeat with i from 2 to limit
if (n mod i is 0) then set sum to sum + i + n div i
end repeat
return sum
end aliquotSum
-- Return n's proper divisors.
on properDivisors(n)
set output to {}
if (n > 1) then
set sqrt to n ^ 0.5
set limit to sqrt div 1
if (limit = sqrt) then
set end of output to limit
set limit to limit - 1
end if
repeat with i from limit to 2 by -1
if (n mod i is 0) then
set beginning of output to i
set end of output to n div i
end if
end repeat
set beginning of output to 1
end if
return output
end properDivisors
-- Does a subset of the given list of numbers add up to the target value?
on subsetOf:numberList sumsTo:target
script o
property lst : numberList
property someNegatives : false
on ssp(target, i)
repeat while (i > 1)
set n to item i of my lst
set i to i - 1
if ((n = target) or (((n < target) or (someNegatives)) and (ssp(target - n, i)))) then return true
end repeat
return (target = beginning of my lst)
end ssp
end script
-- The search can be more efficient if it's known the list contains no negatives.
repeat with n in o's lst
if (n < 0) then
set o's someNegatives to true
exit repeat
end if
end repeat
return o's ssp(target, count o's lst)
end subsetOf:sumsTo:
-- Is n a Zumkeller number?
on isZumkeller(n)
-- Yes if its aliquot sum is greater than or equal to it, the difference between them is even, and
-- either n is odd or a subset of its proper divisors sums to half the sum of the divisors and it.
-- Using aliquotSum() to get the divisor sum and then calling properDivisors() too if a list's actually
-- needed is generally faster than using properDivisors() in the first place and summing the result.
set sum to aliquotSum(n)
return ((sum ≥ n) and ((sum - n) mod 2 = 0) and ¬
((n mod 2 = 1) or (my subsetOf:(properDivisors(n)) sumsTo:((sum + n) div 2))))
end isZumkeller
-- Task code:
-- Find and return q Zumkeller numbers, starting the search at n and continuing at the
-- given interval, applying the Zumkeller test only to numbers passing the given filter.
on zumkellerNumbers(q, n, interval, filter)
script o
property zumkellers : {}
end script
set counter to 0
repeat until (counter = q)
if ((filter's OK(n)) and (isZumkeller(n))) then
set end of o's zumkellers to n
set counter to counter + 1
end if
set n to n + interval
end repeat
return o's zumkellers
end zumkellerNumbers
on joinText(textList, delimiter)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set txt to textList as text
set AppleScript's text item delimiters to astid
return txt
end joinText
on formatForDisplay(resultList, heading, resultsPerLine, separator)
script o
property input : resultList
property output : {heading}
end script
set len to (count o's input)
repeat with i from 1 to len by resultsPerLine
set j to i + resultsPerLine - 1
if (j > len) then set j to len
set end of o's output to joinText(items i thru j of o's input, separator)
end repeat
return joinText(o's output, linefeed)
end formatForDisplay
on doTask(cheating)
set output to {}
script noFilter
on OK(n)
return true
end OK
end script
set header to "1st 220 Zumkeller numbers:"
set end of output to formatForDisplay(zumkellerNumbers(220, 1, 1, noFilter), header, 20, " ")
set header to "1st 40 odd Zumkeller numbers:"
set end of output to formatForDisplay(zumkellerNumbers(40, 1, 2, noFilter), header, 10, " ")
-- Stretch goal:
set header to "1st 40 odd Zumkeller numbers not ending with 5:"
script no5Multiples
on OK(n)
return (n mod 5 > 0)
end OK
end script
if (cheating) then
-- Knowing that the HCF of the first 203 odd Zumkellers not ending with 5
-- is 63, just check 63 and each 126th number thereafter.
-- For the 204th - 907th such numbers, the HCF reduces to 21, so adjust accordingly.
-- (See Horsth's comments on the Talk page.)
set zumkellers to zumkellerNumbers(40, 63, 126, no5Multiples)
else
-- Otherwise check alternate numbers from 1.
set zumkellers to zumkellerNumbers(40, 1, 2, no5Multiples)
end if
set end of output to formatForDisplay(zumkellers, header, 10, " ")
return joinText(output, linefeed & linefeed)
end doTask
local cheating
set cheating to false
doTask(cheating)
- Output:
"1st 220 Zumkeller numbers:
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96
102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198
204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282
294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368
372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462
464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540
544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620
624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708
714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810
812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896
906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984
1st 40 odd Zumkeller numbers:
945 1575 2205 2835 3465 4095 4725 5355 5775 5985
6435 6615 6825 7245 7425 7875 8085 8415 8505 8925
9135 9555 9765 10395 11655 12285 12705 12915 13545 14175
14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
1st 40 odd Zumkeller numbers not ending with 5:
81081 153153 171171 189189 207207 223839 243243 261261 279279 297297
351351 459459 513513 567567 621621 671517 729729 742203 783783 793611
812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709
1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377"
ARM Assembly
/* ARM assembly Raspberry PI */
/* program zumkeller4.s */
/* new version 10/2020 */
/* REMARK 1 : this program use routines in a include file
see task Include a file language arm assembly
for the routine affichageMess conversion10
see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes */
/************************************/
.include "../constantes.inc"
.equ NBDIVISORS, 1000
/*******************************************/
/* Initialized data */
/*******************************************/
.data
szMessStartPgm: .asciz "Program start \n"
szMessEndPgm: .asciz "Program normal end.\n"
szMessErrorArea: .asciz "\033[31mError : area divisors too small.\n"
szMessError: .asciz "\033[31mError !!!\n"
szMessErrGen: .asciz "Error end program.\n"
szMessNbPrem: .asciz "This number is prime !!!.\n"
szMessResultFact: .asciz "@ "
szCarriageReturn: .asciz "\n"
/* datas message display */
szMessEntete: .asciz "The first 220 Zumkeller numbers are:\n"
sNumber: .space 4*20,' '
.space 12,' ' @ for end of conversion
szMessListDivi: .asciz "Divisors list : \n"
szMessListDiviHeap: .asciz "Heap 1 Divisors list : \n"
szMessResult: .ascii " "
sValue: .space 12,' '
.asciz ""
szMessEntete1: .asciz "The first 40 odd Zumkeller numbers are:\n"
szMessEntete2: .asciz "First 40 odd Zumkeller numbers not divisible by 5:\n"
/*******************************************/
/* UnInitialized data */
/*******************************************/
.bss
.align 4
sZoneConv: .skip 24
tbZoneDecom: .skip 8 * NBDIVISORS // facteur 4 octets, nombre 4
/*******************************************/
/* code section */
/*******************************************/
.text
.global main
main: @ program start
ldr r0,iAdrszMessStartPgm @ display start message
bl affichageMess
ldr r0,iAdrszMessEntete @ display result message
bl affichageMess
mov r2,#1
mov r3,#0
mov r4,#0
1:
mov r0,r2 @ number
bl testZumkeller
cmp r0,#1
bne 3f
mov r0,r2
ldr r1,iAdrsNumber @ and convert ascii string
lsl r5,r4,#2
add r1,r5
bl conversion10
add r4,r4,#1
cmp r4,#20
blt 2f
add r1,r1,#3
mov r0,#'\n'
strb r0,[r1]
mov r0,#0
strb r0,[r1,#1]
ldr r0,iAdrsNumber @ display result message
bl affichageMess
mov r4,#0
2:
add r3,r3,#1
3:
add r2,r2,#1
cmp r3,#220
blt 1b
/* odd zumkeller numbers */
ldr r0,iAdrszMessEntete1
bl affichageMess
mov r2,#1
mov r3,#0
mov r4,#0
4:
mov r0,r2 @ number
bl testZumkeller
cmp r0,#1
bne 6f
mov r0,r2
ldr r1,iAdrsNumber @ and convert ascii string
lsl r5,r4,#3
add r1,r5
bl conversion10
add r4,r4,#1
cmp r4,#8
blt 5f
add r1,r1,#8
mov r0,#'\n'
strb r0,[r1]
mov r0,#0
strb r0,[r1,#1]
ldr r0,iAdrsNumber @ display result message
bl affichageMess
mov r4,#0
5:
add r3,r3,#1
6:
add r2,r2,#2
cmp r3,#40
blt 4b
/* odd zumkeller numbers not multiple5 */
61:
ldr r0,iAdrszMessEntete2
bl affichageMess
mov r3,#0
mov r4,#0
7:
lsr r8,r2,#3 @ divide counter by 5
add r8,r8,r2,lsr #4
add r8,r8,r8,lsr #4
add r8,r8,r8,lsr #8
add r8,r8,r8,lsr #16
add r9,r8,r8,lsl #2 @ multiply result by 5
sub r9,r2,r9
mov r6,#13
mul r9,r6,r9
lsr r9,#6
add r9,r8 @ it is a quotient
add r9,r9,r9,lsl #2 @ multiply by 5
sub r9,r2,r9 @ compute remainder
cmp r9,#0 @ remainder = zero ?
beq 9f
mov r0,r2 @ number
bl testZumkeller
cmp r0,#1
bne 9f
mov r0,r2
ldr r1,iAdrsNumber @ and convert ascii string
lsl r5,r4,#3
add r1,r5
bl conversion10
add r4,r4,#1
cmp r4,#8
blt 8f
add r1,r1,#8
mov r0,#'\n'
strb r0,[r1]
mov r0,#0
strb r0,[r1,#1]
ldr r0,iAdrsNumber @ display result message
bl affichageMess
mov r4,#0
8:
add r3,r3,#1
9:
add r2,r2,#2
cmp r3,#40
blt 7b
ldr r0,iAdrszMessEndPgm @ display end message
bl affichageMess
b 100f
99: @ display error message
ldr r0,iAdrszMessError
bl affichageMess
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc 0 @ perform system call
iAdrszMessStartPgm: .int szMessStartPgm
iAdrszMessEndPgm: .int szMessEndPgm
iAdrszMessError: .int szMessError
iAdrszCarriageReturn: .int szCarriageReturn
iAdrszMessResult: .int szMessResult
iAdrsValue: .int sValue
iAdrtbZoneDecom: .int tbZoneDecom
iAdrszMessEntete: .int szMessEntete
iAdrszMessEntete1: .int szMessEntete1
iAdrszMessEntete2: .int szMessEntete2
iAdrsNumber: .int sNumber
/******************************************************************/
/* test if number is Zumkeller number */
/******************************************************************/
/* r0 contains the number */
/* r0 return 1 if Zumkeller number else return 0 */
testZumkeller:
push {r1-r6,lr} @ save registers
mov r6,r0 @ save number
ldr r1,iAdrtbZoneDecom
bl decompFact @ create area of divisors
cmp r0,#1 @ no divisors
movle r0,#0
ble 100f
tst r2,#1 @ odd sum ?
movne r0,#0
bne 100f @ yes -> end
tst r1,#1 @ number of odd divisors is odd ?
movne r0,#0
bne 100f @ yes -> end
lsl r5,r6,#1 @ abondant number
cmp r5,r2
movgt r0,#0
bgt 100f @ no -> end
mov r3,r0
mov r4,r2 @ save sum
ldr r0,iAdrtbZoneDecom
mov r1,#0
mov r2,r3
bl shellSort @ sort table
mov r1,r3 @ factors number
ldr r0,iAdrtbZoneDecom
lsr r2,r4,#1 @ sum / 2
bl computePartIter @
100:
pop {r1-r6,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* search factors to sum = entry value */
/******************************************************************/
/* r0 contains address of divisors area */
/* r1 contains elements number */
/* r2 contains divisors sum / 2 */
/* r0 return 1 if ok 0 else */
computePartIter:
push {r1-r7,fp,lr} @ save registers
lsl r7,r1,#3 @ compute size of temp table
sub sp,r7 @ and reserve on stack
mov fp,sp @ frame pointer = stack address = begin table
mov r5,#0 @ stack indice
sub r3,r1,#1
1:
ldr r4,[r0,r3,lsl #2] @ load factor
cmp r4,r2 @ compare value
bgt 2f
beq 90f @ equal -> end ok
cmp r3,#0 @ first item ?
beq 3f
sub r3,#1 @ push indice item in temp table
add r6,fp,r5,lsl #3
str r3,[r6]
str r2,[r6,#4] @ push sum in temp table
add r5,#1
sub r2,r4 @ substract divisors from sum
b 1b
2:
sub r3,#1 @ other divisors
cmp r3,#0 @ first item ?
bge 1b
3: @ first item
cmp r5,#0 @ stack empty ?
moveq r0,#0 @ no sum factors equal to value
beq 100f @ end
sub r5,#1 @ else pop stack
add r6,fp,r5,lsl #3 @ and restaur
ldr r3,[r6] @ indice
ldr r2,[r6,#4] @ and value
b 1b @ and loop
90:
mov r0,#1 @ it is ok
100:
add sp,r7 @ stack alignement
pop {r1-r7,fp,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* factor decomposition */
/******************************************************************/
/* r0 contains number */
/* r1 contains address of divisors area */
/* r0 return divisors items in table */
/* r1 return the number of odd divisors */
/* r2 return the sum of divisors */
decompFact:
push {r3-r8,lr} @ save registers
mov r5,r1
mov r8,r0 @ save number
bl isPrime @ prime ?
cmp r0,#1
beq 98f @ yes is prime
mov r1,#1
str r1,[r5] @ first factor
mov r12,#1 @ divisors sum
mov r11,#1 @ number odd divisors
mov r4,#1 @ indice divisors table
mov r1,#2 @ first divisor
mov r6,#0 @ previous divisor
mov r7,#0 @ number of same divisors
2:
mov r0,r8 @ dividende
bl division @ r1 divisor r2 quotient r3 remainder
cmp r3,#0
bne 5f @ if remainder <> zero -> no divisor
mov r8,r2 @ else quotient -> new dividende
cmp r1,r6 @ same divisor ?
beq 4f @ yes
mov r7,r4 @ number factors in table
mov r9,#0 @ indice
21:
ldr r10,[r5,r9,lsl #2 ] @ load one factor
mul r10,r1,r10 @ multiply
str r10,[r5,r7,lsl #2] @ and store in the table
tst r10,#1 @ divisor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 21b
mov r4,r7
mov r6,r1 @ new divisor
b 7f
4: @ same divisor
sub r9,r4,#1
mov r7,r4
41:
ldr r10,[r5,r9,lsl #2 ]
cmp r10,r1
subne r9,#1
bne 41b
sub r9,r4,r9
42:
ldr r10,[r5,r9,lsl #2 ]
mul r10,r1,r10
str r10,[r5,r7,lsl #2] @ and store in the table
tst r10,#1 @ divsor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 42b
mov r4,r7
b 7f @ and loop
/* not divisor -> increment next divisor */
5:
cmp r1,#2 @ if divisor = 2 -> add 1
addeq r1,#1
addne r1,#2 @ else add 2
b 2b
/* divisor -> test if new dividende is prime */
7:
mov r3,r1 @ save divisor
cmp r8,#1 @ dividende = 1 ? -> end
beq 10f
mov r0,r8 @ new dividende is prime ?
mov r1,#0
bl isPrime @ the new dividende is prime ?
cmp r0,#1
bne 10f @ the new dividende is not prime
cmp r8,r6 @ else dividende is same divisor ?
beq 9f @ yes
mov r7,r4 @ number factors in table
mov r9,#0 @ indice
71:
ldr r10,[r5,r9,lsl #2 ] @ load one factor
mul r10,r8,r10 @ multiply
str r10,[r5,r7,lsl #2] @ and store in the table
tst r10,#1 @ divsor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 71b
mov r4,r7
mov r7,#0
b 11f
9:
sub r9,r4,#1
mov r7,r4
91:
ldr r10,[r5,r9,lsl #2 ]
cmp r10,r8
subne r9,#1
bne 91b
sub r9,r4,r9
92:
ldr r10,[r5,r9,lsl #2 ]
mul r10,r8,r10
str r10,[r5,r7,lsl #2] @ and store in the table
tst r10,#1 @ divisor odd ?
addne r11,#1
add r12,r10
add r7,r7,#1 @ and increment counter
add r9,r9,#1
cmp r9,r4
blt 92b
mov r4,r7
b 11f
10:
mov r1,r3 @ current divisor = new divisor
cmp r1,r8 @ current divisor > new dividende ?
ble 2b @ no -> loop
/* end decomposition */
11:
mov r0,r4 @ return number of table items
mov r2,r12 @ return sum
mov r1,r11 @ return number of odd divisor
mov r3,#0
str r3,[r5,r4,lsl #2] @ store zéro in last table item
b 100f
98:
//ldr r0,iAdrszMessNbPrem
//bl affichageMess
mov r0,#1 @ return code
b 100f
99:
ldr r0,iAdrszMessError
bl affichageMess
mov r0,#-1 @ error code
b 100f
100:
pop {r3-r8,lr} @ restaur registers
bx lr
iAdrszMessNbPrem: .int szMessNbPrem
/***************************************************/
/* check if a number is prime */
/***************************************************/
/* r0 contains the number */
/* r0 return 1 if prime 0 else */
@2147483647
@4294967297
@131071
isPrime:
push {r1-r6,lr} @ save registers
cmp r0,#0
beq 90f
cmp r0,#17
bhi 1f
cmp r0,#3
bls 80f @ for 1,2,3 return prime
cmp r0,#5
beq 80f @ for 5 return prime
cmp r0,#7
beq 80f @ for 7 return prime
cmp r0,#11
beq 80f @ for 11 return prime
cmp r0,#13
beq 80f @ for 13 return prime
cmp r0,#17
beq 80f @ for 17 return prime
1:
tst r0,#1 @ even ?
beq 90f @ yes -> not prime
mov r2,r0 @ save number
sub r1,r0,#1 @ exposant n - 1
mov r0,#3 @ base
bl moduloPuR32 @ compute base power n - 1 modulo n
cmp r0,#1
bne 90f @ if <> 1 -> not prime
mov r0,#5
bl moduloPuR32
cmp r0,#1
bne 90f
mov r0,#7
bl moduloPuR32
cmp r0,#1
bne 90f
mov r0,#11
bl moduloPuR32
cmp r0,#1
bne 90f
mov r0,#13
bl moduloPuR32
cmp r0,#1
bne 90f
mov r0,#17
bl moduloPuR32
cmp r0,#1
bne 90f
80:
mov r0,#1 @ is prime
b 100f
90:
mov r0,#0 @ no prime
100: @ fin standard de la fonction
pop {r1-r6,lr} @ restaur des registres
bx lr @ retour de la fonction en utilisant lr
/********************************************************/
/* Calcul modulo de b puissance e modulo m */
/* Exemple 4 puissance 13 modulo 497 = 445 */
/* */
/********************************************************/
/* r0 nombre */
/* r1 exposant */
/* r2 modulo */
/* r0 return result */
moduloPuR32:
push {r1-r7,lr} @ save registers
cmp r0,#0 @ verif <> zero
beq 100f
cmp r2,#0 @ verif <> zero
beq 100f @ TODO: vérifier les cas d erreur
1:
mov r4,r2 @ save modulo
mov r5,r1 @ save exposant
mov r6,r0 @ save base
mov r3,#1 @ start result
mov r1,#0 @ division de r0,r1 par r2
bl division32R
mov r6,r2 @ base <- remainder
2:
tst r5,#1 @ exposant even or odd
beq 3f
umull r0,r1,r6,r3
mov r2,r4
bl division32R
mov r3,r2 @ result <- remainder
3:
umull r0,r1,r6,r6
mov r2,r4
bl division32R
mov r6,r2 @ base <- remainder
lsr r5,#1 @ left shift 1 bit
cmp r5,#0 @ end ?
bne 2b
mov r0,r3
100: @ fin standard de la fonction
pop {r1-r7,lr} @ restaur des registres
bx lr @ retour de la fonction en utilisant lr
/***************************************************/
/* division number 64 bits in 2 registers by number 32 bits */
/***************************************************/
/* r0 contains lower part dividende */
/* r1 contains upper part dividende */
/* r2 contains divisor */
/* r0 return lower part quotient */
/* r1 return upper part quotient */
/* r2 return remainder */
division32R:
push {r3-r9,lr} @ save registers
mov r6,#0 @ init upper upper part remainder !!
mov r7,r1 @ init upper part remainder with upper part dividende
mov r8,r0 @ init lower part remainder with lower part dividende
mov r9,#0 @ upper part quotient
mov r4,#0 @ lower part quotient
mov r5,#32 @ bits number
1: @ begin loop
lsl r6,#1 @ shift upper upper part remainder
lsls r7,#1 @ shift upper part remainder
orrcs r6,#1
lsls r8,#1 @ shift lower part remainder
orrcs r7,#1
lsls r4,#1 @ shift lower part quotient
lsl r9,#1 @ shift upper part quotient
orrcs r9,#1
@ divisor sustract upper part remainder
subs r7,r2
sbcs r6,#0 @ and substract carry
bmi 2f @ négative ?
@ positive or equal
orr r4,#1 @ 1 -> right bit quotient
b 3f
2: @ negative
orr r4,#0 @ 0 -> right bit quotient
adds r7,r2 @ and restaur remainder
adc r6,#0
3:
subs r5,#1 @ decrement bit size
bgt 1b @ end ?
mov r0,r4 @ lower part quotient
mov r1,r9 @ upper part quotient
mov r2,r7 @ remainder
100: @ function end
pop {r3-r9,lr} @ restaur registers
bx lr
/***************************************************/
/* shell Sort */
/***************************************************/
/* r0 contains the address of table */
/* r1 contains the first element but not use !! */
/* this routine use first element at index zero !!! */
/* r2 contains the number of element */
shellSort:
push {r0-r7,lr} @save registers
sub r2,#1 @ index last item
mov r1,r2 @ init gap = last item
1: @ start loop 1
lsrs r1,#1 @ gap = gap / 2
beq 100f @ if gap = 0 -> end
mov r3,r1 @ init loop indice 1
2: @ start loop 2
ldr r4,[r0,r3,lsl #2] @ load first value
mov r5,r3 @ init loop indice 2
3: @ start loop 3
cmp r5,r1 @ indice < gap
blt 4f @ yes -> end loop 2
sub r6,r5,r1 @ index = indice - gap
ldr r7,[r0,r6,lsl #2] @ load second value
cmp r4,r7 @ compare values
strlt r7,[r0,r5,lsl #2] @ store if <
sublt r5,r1 @ indice = indice - gap
blt 3b @ and loop
4: @ end loop 3
str r4,[r0,r5,lsl #2] @ store value 1 at indice 2
add r3,#1 @ increment indice 1
cmp r3,r2 @ end ?
ble 2b @ no -> loop 2
b 1b @ yes loop for new gap
100: @ end function
pop {r0-r7,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* display divisors function */
/******************************************************************/
/* r0 contains address of divisors area */
/* r1 contains the number of area items */
displayDivisors:
push {r2-r8,lr} @ save registers
cmp r1,#0
beq 100f
mov r2,r1
mov r3,#0 @ indice
mov r4,r0
1:
add r5,r4,r3,lsl #2
ldr r0,[r5] @ load factor
ldr r1,iAdrsZoneConv
bl conversion10 @ call décimal conversion
ldr r0,iAdrszMessResultFact
ldr r1,iAdrsZoneConv @ insert conversion in message
bl strInsertAtCharInc
bl affichageMess @ display message
add r3,#1 @ other ithem
cmp r3,r2 @ items maxi ?
blt 1b
ldr r0,iAdrszCarriageReturn
bl affichageMess
b 100f
100:
pop {r2-r8,lr} @ restaur registers
bx lr @ return
iAdrszMessResultFact: .int szMessResultFact
iAdrsZoneConv: .int sZoneConv
/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../affichage.inc"
Program start The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not divisible by 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377 Program normal end.
C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace ZumkellerNumbers {
class Program {
static List<int> GetDivisors(int n) {
List<int> divs = new List<int> {
1, n
};
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
int j = n / i;
divs.Add(i);
if (i != j) {
divs.Add(j);
}
}
}
return divs;
}
static bool IsPartSum(List<int> divs, int sum) {
if (sum == 0) {
return true;
}
var le = divs.Count;
if (le == 0) {
return false;
}
var last = divs[le - 1];
List<int> newDivs = new List<int>();
for (int i = 0; i < le - 1; i++) {
newDivs.Add(divs[i]);
}
if (last > sum) {
return IsPartSum(newDivs, sum);
}
return IsPartSum(newDivs, sum) || IsPartSum(newDivs, sum - last);
}
static bool IsZumkeller(int n) {
var divs = GetDivisors(n);
var sum = divs.Sum();
// if sum is odd can't be split into two partitions with equal sums
if (sum % 2 == 1) {
return false;
}
// if n is odd use 'abundant odd number' optimization
if (n % 2 == 1) {
var abundance = sum - 2 * n;
return abundance > 0 && abundance % 2 == 0;
}
// if n and sum are both even check if there's a partition which totals sum / 2
return IsPartSum(divs, sum / 2);
}
static void Main() {
Console.WriteLine("The first 220 Zumkeller numbers are:");
int i = 2;
for (int count = 0; count < 220; i++) {
if (IsZumkeller(i)) {
Console.Write("{0,3} ", i);
count++;
if (count % 20 == 0) {
Console.WriteLine();
}
}
}
Console.WriteLine("\nThe first 40 odd Zumkeller numbers are:");
i = 3;
for (int count = 0; count < 40; i += 2) {
if (IsZumkeller(i)) {
Console.Write("{0,5} ", i);
count++;
if (count % 10 == 0) {
Console.WriteLine();
}
}
}
Console.WriteLine("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:");
i = 3;
for (int count = 0; count < 40; i += 2) {
if (i % 10 != 5 && IsZumkeller(i)) {
Console.Write("{0,7} ", i);
count++;
if (count % 8 == 0) {
Console.WriteLine();
}
}
}
}
}
}
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
C++
#include <iostream">
#include <cmath>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <numeric>
using namespace std;
// Returns n in binary right justified with length passed and padded with zeroes
const uint* binary(uint n, uint length);
// Returns the sum of the binary ordered subset of rank r.
// Adapted from Sympy implementation.
uint sum_subset_unrank_bin(const vector<uint>& d, uint r);
vector<uint> factors(uint x);
bool isPrime(uint number);
bool isZum(uint n);
ostream& operator<<(ostream& os, const vector<uint>& zumz) {
for (uint i = 0; i < zumz.size(); i++) {
if (i % 10 == 0)
os << endl;
os << setw(10) << zumz[i] << ' ';
}
return os;
}
int main() {
cout << "First 220 Zumkeller numbers:" << endl;
vector<uint> zumz;
for (uint n = 2; zumz.size() < 220; n++)
if (isZum(n))
zumz.push_back(n);
cout << zumz << endl << endl;
cout << "First 40 odd Zumkeller numbers:" << endl;
vector<uint> zumz2;
for (uint n = 2; zumz2.size() < 40; n++)
if (n % 2 && isZum(n))
zumz2.push_back(n);
cout << zumz2 << endl << endl;
cout << "First 40 odd Zumkeller numbers not ending in 5:" << endl;
vector<uint> zumz3;
for (uint n = 2; zumz3.size() < 40; n++)
if (n % 2 && (n % 10) != 5 && isZum(n))
zumz3.push_back(n);
cout << zumz3 << endl << endl;
return 0;
}
// Returns n in binary right justified with length passed and padded with zeroes
const uint* binary(uint n, uint length) {
uint* bin = new uint[length]; // array to hold result
fill(bin, bin + length, 0); // fill with zeroes
// convert n to binary and store right justified in bin
for (uint i = 0; n > 0; i++) {
uint rem = n % 2;
n /= 2;
if (rem)
bin[length - 1 - i] = 1;
}
return bin;
}
// Returns the sum of the binary ordered subset of rank r.
// Adapted from Sympy implementation.
uint sum_subset_unrank_bin(const vector<uint>& d, uint r) {
vector<uint> subset;
// convert r to binary array of same size as d
const uint* bits = binary(r, d.size() - 1);
// get binary ordered subset
for (uint i = 0; i < d.size() - 1; i++)
if (bits[i])
subset.push_back(d[i]);
delete[] bits;
return accumulate(subset.begin(), subset.end(), 0u);
}
vector<uint> factors(uint x) {
vector<uint> result;
// this will loop from 1 to int(sqrt(x))
for (uint i = 1; i * i <= x; i++) {
// Check if i divides x without leaving a remainder
if (x % i == 0) {
result.push_back(i);
if (x / i != i)
result.push_back(x / i);
}
}
// return the sorted factors of x
sort(result.begin(), result.end());
return result;
}
bool isPrime(uint number) {
if (number < 2) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
for (uint i = 3; i * i <= number; i += 2)
if (number % i == 0) return false;
return true;
}
bool isZum(uint n) {
// if prime it ain't no zum
if (isPrime(n))
return false;
// get sum of divisors
const auto d = factors(n);
uint s = accumulate(d.begin(), d.end(), 0u);
// if sum is odd or sum < 2*n it ain't no zum
if (s % 2 || s < 2 * n)
return false;
// if we get here and n is odd or n has at least 24 divisors it's a zum!
// Valid for even n < 99504. To test n beyond this bound, comment out this condition.
// And wait all day. Thanks to User:Horsth for taking the time to find this bound!
if (n % 2 || d.size() >= 24)
return true;
if (!(s % 2) && d[d.size() - 1] <= s / 2)
for (uint x = 2; (uint) log2(x) < (d.size() - 1); x++) // using log2 prevents overflow
if (sum_subset_unrank_bin(d, x) == s / 2)
return true; // congratulations it's a zum num!!
// if we get here it ain't no zum
return false;
}
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not ending in 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
D
import std.algorithm;
import std.stdio;
int[] getDivisors(int n) {
auto divs = [1, n];
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
divs ~= i;
int j = n / i;
if (i != j) {
divs ~= j;
}
}
}
return divs;
}
bool isPartSum(int[] divs, int sum) {
if (sum == 0) {
return true;
}
auto le = divs.length;
if (le == 0) {
return false;
}
auto last = divs[$ - 1];
int[] newDivs;
for (int i = 0; i < le - 1; i++) {
newDivs ~= divs[i];
}
if (last > sum) {
return isPartSum(newDivs, sum);
} else {
return isPartSum(newDivs, sum) || isPartSum(newDivs, sum - last);
}
}
bool isZumkeller(int n) {
auto divs = getDivisors(n);
auto sum = divs.sum();
// if sum is odd can't be split into two partitions with equal sums
if (sum % 2 == 1) {
return false;
}
// if n is odd use 'abundant odd number' optimization
if (n % 2 == 1) {
auto abundance = sum - 2 * n;
return abundance > 0 && abundance % 2 == 0;
}
// if n and sum are both even check if there's a partition which totals sum / 2
return isPartSum(divs, sum / 2);
}
void main() {
writeln("The first 220 Zumkeller numbers are:");
int i = 2;
for (int count = 0; count < 220; i++) {
if (isZumkeller(i)) {
writef("%3d ", i);
count++;
if (count % 20 == 0) {
writeln;
}
}
}
writeln("\nThe first 40 odd Zumkeller numbers are:");
i = 3;
for (int count = 0; count < 40; i += 2) {
if (isZumkeller(i)) {
writef("%5d ", i);
count++;
if (count % 10 == 0) {
writeln;
}
}
}
writeln("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:");
i = 3;
for (int count = 0; count < 40; i += 2) {
if (i % 10 != 5 && isZumkeller(i)) {
writef("%7d ", i);
count++;
if (count % 8 == 0) {
writeln;
}
}
}
}
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
EasyLang
proc divisors n . divs[] .
divs[] = [ 1 n ]
for i = 2 to sqrt n
if n mod i = 0
j = n / i
divs[] &= i
if i <> j
divs[] &= j
.
.
.
.
func ispartsum divs[] sum .
if sum = 0
return 1
.
if len divs[] = 0
return 0
.
last = divs[len divs[]]
len divs[] -1
if last > sum
return ispartsum divs[] sum
.
if ispartsum divs[] sum = 1
return 1
.
return ispartsum divs[] (sum - last)
.
func iszumkeller n .
divisors n divs[]
for v in divs[]
sum += v
.
if sum mod 2 = 1
return 0
.
if n mod 2 = 1
abund = sum - 2 * n
return if abund > 0 and abund mod 2 = 0
.
return ispartsum divs[] (sum / 2)
.
#
print "The first 220 Zumkeller numbers are:"
i = 2
repeat
if iszumkeller i = 1
write i & " "
count += 1
.
until count = 220
i += 1
.
print "\n\nThe first 40 odd Zumkeller numbers are:"
count = 0
i = 3
repeat
if iszumkeller i = 1
write i & " "
count += 1
.
until count = 40
i += 2
.
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
F#
This task uses [1]
// Zumkeller numbers: Nigel Galloway. May 16th., 2021
let rec fG n g=match g with h::_ when h>=n->h=n |h::t->fG n t || fG(n-h) t |_->false
let fN g=function n when n&&&1=1->false
|n->let e=n/2-g in match compare e 0 with 0->true
|1->let l=[1..e]|>List.filter(fun n->g%n=0)
match compare(l|>List.sum) e with 1->fG e l |0->true |_->false
|_->false
Seq.initInfinite((+)1)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 220|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n"
Seq.initInfinite((*)2>>(+)1)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 40|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n"
Seq.initInfinite((*)2>>(+)1)|>Seq.filter(fun n->n%10<>5)|>Seq.map(fun n->(n,sod n))|>Seq.filter(fun(n,g)->fN n g)|>Seq.take 40|>Seq.iter(fun(n,_)->printf "%d " n); printfn "\n"
- Output:
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Factor
USING: combinators grouping io kernel lists lists.lazy math
math.primes.factors memoize prettyprint sequences ;
MEMO: psum? ( seq n -- ? )
{
{ [ dup zero? ] [ 2drop t ] }
{ [ over length zero? ] [ 2drop f ] }
{ [ over last over > ] [ [ but-last ] dip psum? ] }
[
[ [ but-last ] dip psum? ]
[ over last - [ but-last ] dip psum? ] 2bi or
]
} cond ;
: zumkeller? ( n -- ? )
dup divisors dup sum
{
{ [ dup odd? ] [ 3drop f ] }
{ [ pick odd? ] [ nip swap 2 * - [ 0 > ] [ even? ] bi and ] }
[ nipd 2/ psum? ]
} cond ;
: zumkellers ( -- list )
1 lfrom [ zumkeller? ] lfilter ;
: odd-zumkellers ( -- list )
1 [ 2 + ] lfrom-by [ zumkeller? ] lfilter ;
: odd-zumkellers-no-5 ( -- list )
odd-zumkellers [ 5 mod zero? not ] lfilter ;
: show ( count list row-len -- )
[ ltake list>array ] dip group simple-table. nl ;
"First 220 Zumkeller numbers:" print
220 zumkellers 20 show
"First 40 odd Zumkeller numbers:" print
40 odd-zumkellers 10 show
"First 40 odd Zumkeller numbers not ending with 5:" print
40 odd-zumkellers-no-5 8 show
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not ending with 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Go
package main
import "fmt"
func getDivisors(n int) []int {
divs := []int{1, n}
for i := 2; i*i <= n; i++ {
if n%i == 0 {
j := n / i
divs = append(divs, i)
if i != j {
divs = append(divs, j)
}
}
}
return divs
}
func sum(divs []int) int {
sum := 0
for _, div := range divs {
sum += div
}
return sum
}
func isPartSum(divs []int, sum int) bool {
if sum == 0 {
return true
}
le := len(divs)
if le == 0 {
return false
}
last := divs[le-1]
divs = divs[0 : le-1]
if last > sum {
return isPartSum(divs, sum)
}
return isPartSum(divs, sum) || isPartSum(divs, sum-last)
}
func isZumkeller(n int) bool {
divs := getDivisors(n)
sum := sum(divs)
// if sum is odd can't be split into two partitions with equal sums
if sum%2 == 1 {
return false
}
// if n is odd use 'abundant odd number' optimization
if n%2 == 1 {
abundance := sum - 2*n
return abundance > 0 && abundance%2 == 0
}
// if n and sum are both even check if there's a partition which totals sum / 2
return isPartSum(divs, sum/2)
}
func main() {
fmt.Println("The first 220 Zumkeller numbers are:")
for i, count := 2, 0; count < 220; i++ {
if isZumkeller(i) {
fmt.Printf("%3d ", i)
count++
if count%20 == 0 {
fmt.Println()
}
}
}
fmt.Println("\nThe first 40 odd Zumkeller numbers are:")
for i, count := 3, 0; count < 40; i += 2 {
if isZumkeller(i) {
fmt.Printf("%5d ", i)
count++
if count%10 == 0 {
fmt.Println()
}
}
}
fmt.Println("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:")
for i, count := 3, 0; count < 40; i += 2 {
if (i % 10 != 5) && isZumkeller(i) {
fmt.Printf("%7d ", i)
count++
if count%8 == 0 {
fmt.Println()
}
}
}
fmt.Println()
}
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Haskell
import Data.List (group, sort)
import Data.List.Split (chunksOf)
import Data.Numbers.Primes (primeFactors)
-------------------- ZUMKELLER NUMBERS -------------------
isZumkeller :: Int -> Bool
isZumkeller n =
let ds = divisors n
m = sum ds
in ( even m
&& let half = div m 2
in elem half ds
|| ( all (half >=) ds
&& summable half ds
)
)
summable :: Int -> [Int] -> Bool
summable _ [] = False
summable x xs@(h : t) =
elem x xs
|| summable (x - h) t
|| summable x t
divisors :: Int -> [Int]
divisors x =
sort
( foldr
( flip ((<*>) . fmap (*))
. scanl (*) 1
)
[1]
(group (primeFactors x))
)
--------------------------- TEST -------------------------
main :: IO ()
main =
mapM_
( \(s, n, xs) ->
putStrLn $
s
<> ( '\n' :
tabulated
10
(take n (filter isZumkeller xs))
)
)
[ ("First 220 Zumkeller numbers:", 220, [1 ..]),
("First 40 odd Zumkeller numbers:", 40, [1, 3 ..])
]
------------------------- DISPLAY ------------------------
tabulated ::
Show a =>
Int ->
[a] ->
String
tabulated nCols = go
where
go xs =
let ts = show <$> xs
w = succ (maximum (length <$> ts))
in unlines
( concat
<$> chunksOf
nCols
(justifyRight w ' ' <$> ts)
)
justifyRight :: Int -> Char -> String -> String
justifyRight n c = (drop . length) <*> (replicate n c <>)
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
J
Implementation:
divisors=: {{ \:~ */@>,{ (^ i.@>:)&.">/ __ q: y }}
zum=: {{
if. 2|s=. +/divs=. divisors y do. 0
elseif. 2|y do. (0<k) * 0=2|k=. s-2*y
else. s=. -:s for_d. divs do. if. d<:s do. s=. s-d end. end. s=0
end.
}}@>
Task examples:
10 22$1+I.zum 1+i.1000 NB. first 220 Zumkeller numbers
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104
108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216
220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312
318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408
414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498
500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588
594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684
690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786
792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888
894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984
4 10$1+2*I.zum 1+2*i.1e4 NB. first 40 odd Zumkeller numbers
945 1575 2205 2835 3465 4095 4725 5355 5775 5985
6435 6615 6825 7245 7425 7875 8085 8415 8505 8925
9135 9555 9765 10395 11655 12285 12705 12915 13545 14175
14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
4 10$(#~ 0~:5|])1+2*I.zum 1+2*i.1e6 NB. first 40 odd Zumkeller numbers not divisible by 5
81081 153153 171171 189189 207207 223839 243243 261261 279279 297297
351351 459459 513513 567567 621621 671517 729729 742203 783783 793611
812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709
1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ZumkellerNumbers {
public static void main(String[] args) {
int n = 1;
System.out.printf("First 220 Zumkeller numbers:%n");
for ( int count = 1 ; count <= 220 ; n += 1 ) {
if ( isZumkeller(n) ) {
System.out.printf("%3d ", n);
if ( count % 20 == 0 ) {
System.out.printf("%n");
}
count++;
}
}
n = 1;
System.out.printf("%nFirst 40 odd Zumkeller numbers:%n");
for ( int count = 1 ; count <= 40 ; n += 2 ) {
if ( isZumkeller(n) ) {
System.out.printf("%6d", n);
if ( count % 10 == 0 ) {
System.out.printf("%n");
}
count++;
}
}
n = 1;
System.out.printf("%nFirst 40 odd Zumkeller numbers that do not end in a 5:%n");
for ( int count = 1 ; count <= 40 ; n += 2 ) {
if ( n % 5 != 0 && isZumkeller(n) ) {
System.out.printf("%8d", n);
if ( count % 10 == 0 ) {
System.out.printf("%n");
}
count++;
}
}
}
private static boolean isZumkeller(int n) {
// numbers congruent to 6 or 12 modulo 18 are Zumkeller numbers
if ( n % 18 == 6 || n % 18 == 12 ) {
return true;
}
List<Integer> divisors = getDivisors(n);
int divisorSum = divisors.stream().mapToInt(i -> i.intValue()).sum();
// divisor sum cannot be odd
if ( divisorSum % 2 == 1 ) {
return false;
}
// numbers where n is odd and the abundance is even are Zumkeller numbers
int abundance = divisorSum - 2 * n;
if ( n % 2 == 1 && abundance > 0 && abundance % 2 == 0 ) {
return true;
}
Collections.sort(divisors);
int j = divisors.size() - 1;
int sum = divisorSum/2;
// Largest divisor larger than sum - then cannot partition and not Zumkeller number
if ( divisors.get(j) > sum ) {
return false;
}
return canPartition(j, divisors, sum, new int[2]);
}
private static boolean canPartition(int j, List<Integer> divisors, int sum, int[] buckets) {
if ( j < 0 ) {
return true;
}
for ( int i = 0 ; i < 2 ; i++ ) {
if ( buckets[i] + divisors.get(j) <= sum ) {
buckets[i] += divisors.get(j);
if ( canPartition(j-1, divisors, sum, buckets) ) {
return true;
}
buckets[i] -= divisors.get(j);
}
if( buckets[i] == 0 ) {
break;
}
}
return false;
}
private static final List<Integer> getDivisors(int number) {
List<Integer> divisors = new ArrayList<Integer>();
long sqrt = (long) Math.sqrt(number);
for ( int i = 1 ; i <= sqrt ; i++ ) {
if ( number % i == 0 ) {
divisors.add(i);
int div = number / i;
if ( div != i ) {
divisors.add(div);
}
}
}
return divisors;
}
}
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers that do not end in a 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
jq
From a practical point of view, jq is not well-suited to these tasks, e.g. using the program shown here, the first task (computing the first 220 Zumkeller numbers) takes about 1 second.
The main point of interest here, therefore, is the partitioning function, or rather how a generic partitioning function that generates a stream of partitions is easily transformed into a specialized function that prunes irrelevant partitions efficiently.
# The factors, sorted
def factors:
. as $num
| reduce range(1; 1 + sqrt|floor) as $i
([];
if ($num % $i) == 0 then
($num / $i) as $r
| if $i == $r then . + [$i] else . + [$i, $r] end
else .
end
| sort) ;
# If the input is a sorted array of distinct non-negative integers,
# then the output will be a stream of [$x,$y] arrays,
# where $x and $y are non-empty arrays that partition the
# input, and where ($x|add) == $sum.
# If [$x,$y] is emitted, then [$y,$x] will not also be emitted.
# The items in $x appear in the same order as in the input, and similarly
# for $y.
#
def distinct_partitions($sum):
# input: [$array, $n, $lim] where $n>0
# output: a stream of arrays, $a, each with $n distinct items from $array,
# preserving the order in $array, and such that
# add == $lim
def p:
. as [$in, $n, $lim]
| if $n==1 # this condition is very common so it saves time to check early on
then ($in | bsearch($lim)) as $ix
| if $ix < 0 then empty
else [$lim]
end
else ($in|length) as $length
| if $length <= $n then empty
elif $length==$n then $in | select(add == $lim)
elif ($in[-$n:]|add) < $lim then empty
else ($in[:$n]|add) as $rsum
| if $rsum > $lim then empty
elif $rsum == $lim then "amazing" | debug | $in[:$n]
else range(0; 1 + $length - $n) as $i
| [$in[$i]] + ([$in[$i+1:], $n-1, $lim - $in[$i]]|p)
end
end
end;
range(1; (1+length)/2) as $i
| ([., $i, $sum]|p) as $pi
| [ $pi, (. - $pi)]
| select( if (.[0]|length) == (.[1]|length) then (.[0] < .[1]) else true end) #1
;
def zumkellerPartitions:
factors
| add as $sum
| if $sum % 2 == 1 then empty
else distinct_partitions($sum / 2)
end;
def is_zumkeller:
first(factors
| add as $sum
| if $sum % 2 == 1 then empty
else distinct_partitions($sum / 2)
| select( (.[0]|add) == (.[1]|add)) // ("internal error: \(.)" | debug | empty) #2
end
| true)
// false;
## The tasks:
"First 220:", limit(220; range(2; infinite) | select(is_zumkeller)),
""
"First 40 odd:", limit(40; range(3; infinite; 2) | select(is_zumkeller))
- Output:
First 220: 6 12 20 24 28 ... 984 First 40 odd: 945 1575 2205 2835 3465 ... 19305
Julia
using Primes
function factorize(n)
f = [one(n)]
for (p, x) in factor(n)
f = reduce(vcat, [f*p^i for i in 1:x], init=f)
end
f
end
function cansum(goal, list)
if goal == 0 || list[1] == goal
return true
elseif length(list) > 1
if list[1] > goal
return cansum(goal, list[2:end])
else
return cansum(goal - list[1], list[2:end]) || cansum(goal, list[2:end])
end
end
return false
end
function iszumkeller(n)
f = reverse(factorize(n))
fsum = sum(f)
return iseven(fsum) && cansum(div(fsum, 2) - f[1], f[2:end])
end
function printconditionalnum(condition, maxcount, numperline = 20)
count, spacing = 1, div(80, numperline)
for i in 1:typemax(Int)
if condition(i)
count += 1
print(rpad(i, spacing), (count - 1) % numperline == 0 ? "\n" : "")
if count > maxcount
return
end
end
end
end
println("First 220 Zumkeller numbers:")
printconditionalnum(iszumkeller, 220)
println("\n\nFirst 40 odd Zumkeller numbers:")
printconditionalnum((n) -> isodd(n) && iszumkeller(n), 40, 8)
println("\n\nFirst 40 odd Zumkeller numbers not ending with 5:")
printconditionalnum((n) -> isodd(n) && (string(n)[end] != '5') && iszumkeller(n), 40, 8)
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not ending with 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Kotlin
import java.util.ArrayList
import kotlin.math.sqrt
object ZumkellerNumbers {
@JvmStatic
fun main(args: Array<String>) {
var n = 1
println("First 220 Zumkeller numbers:")
run {
var count = 1
while (count <= 220) {
if (isZumkeller(n)) {
print("%3d ".format(n))
if (count % 20 == 0) {
println()
}
count++
}
n += 1
}
}
n = 1
println("\nFirst 40 odd Zumkeller numbers:")
run {
var count = 1
while (count <= 40) {
if (isZumkeller(n)) {
print("%6d".format(n))
if (count % 10 == 0) {
println()
}
count++
}
n += 2
}
}
n = 1
println("\nFirst 40 odd Zumkeller numbers that do not end in a 5:")
var count = 1
while (count <= 40) {
if (n % 5 != 0 && isZumkeller(n)) {
print("%8d".format(n))
if (count % 10 == 0) {
println()
}
count++
}
n += 2
}
}
private fun isZumkeller(n: Int): Boolean { // numbers congruent to 6 or 12 modulo 18 are Zumkeller numbers
if (n % 18 == 6 || n % 18 == 12) {
return true
}
val divisors = getDivisors(n)
val divisorSum = divisors.stream().mapToInt { i: Int? -> i!! }.sum()
// divisor sum cannot be odd
if (divisorSum % 2 == 1) {
return false
}
// numbers where n is odd and the abundance is even are Zumkeller numbers
val abundance = divisorSum - 2 * n
if (n % 2 == 1 && abundance > 0 && abundance % 2 == 0) {
return true
}
divisors.sort()
val j = divisors.size - 1
val sum = divisorSum / 2
// Largest divisor larger than sum - then cannot partition and not Zumkeller number
return if (divisors[j] > sum) false else canPartition(j, divisors, sum, IntArray(2))
}
private fun canPartition(j: Int, divisors: List<Int>, sum: Int, buckets: IntArray): Boolean {
if (j < 0) {
return true
}
for (i in 0..1) {
if (buckets[i] + divisors[j] <= sum) {
buckets[i] += divisors[j]
if (canPartition(j - 1, divisors, sum, buckets)) {
return true
}
buckets[i] -= divisors[j]
}
if (buckets[i] == 0) {
break
}
}
return false
}
private fun getDivisors(number: Int): MutableList<Int> {
val divisors: MutableList<Int> = ArrayList()
val sqrt = sqrt(number.toDouble()).toLong()
for (i in 1..sqrt) {
if (number % i == 0L) {
divisors.add(i.toInt())
val div = (number / i).toInt()
if (div.toLong() != i) {
divisors.add(div)
}
}
}
return divisors
}
}
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers that do not end in a 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Lobster
import std
// Derived from Julia and Python versions
def get_divisors(n: int) -> [int]:
var i = 2
let d = [1, n]
let limit = sqrt(n)
while i <= limit:
if n % i == 0:
let j = n / i
push(d,i)
if i != j:
push(d,j)
i += 1
return d
def isPartSum(divs: [int], sum: int) -> bool:
if sum == 0:
return true
let len = length(divs)
if len == 0:
return false
let last = pop(divs)
if last > sum:
return isPartSum(divs, sum)
return isPartSum(copy(divs), sum) or isPartSum(divs, sum-last)
def isZumkeller(n: int) -> bool:
let divs = get_divisors(n)
let sum = fold(divs, 0): _a+_b
if sum % 2 == 1:
// if sum is odd can't be split into two partitions with equal sums
return false
if n % 2 == 1:
// if n is odd use 'abundant odd number' optimization
let abundance = sum - 2 * n
return abundance > 0 and abundance % 2 == 0
return isPartSum(divs, sum/2)
def printZumkellers(q: int, oddonly: bool):
var nprinted = 0
var res = ""
for(100000) n:
if (!oddonly or n % 2 != 0):
if isZumkeller(n):
let s = string(n)
let z = length(s)
res = concat_string([res, repeat_string(" ",8-z), s], "")
nprinted += 1
if nprinted % 10 == 0 or nprinted >= q:
print res
res = ""
if nprinted >= q:
return
print "220 Zumkeller numbers:"
printZumkellers(220, false)
print "\n\n40 odd Zumkeller numbers:"
printZumkellers(40, true)
- Output:
220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
Mathematica / Wolfram Language
ClearAll[ZumkellerQ]
ZumkellerQ[n_] := Module[{d = Divisors[n], t, ds, x},
ds = Total[d];
If[Mod[ds, 2] == 1,
False
,
t = CoefficientList[Product[1 + x^i, {i, d}], x];
t[[1 + ds/2]] > 0
]
];
i = 1;
res = {};
While[Length[res] < 220,
r = ZumkellerQ[i];
If[r, AppendTo[res, i]];
i++;
];
res
i = 1;
res = {};
While[Length[res] < 40,
r = ZumkellerQ[i];
If[r, AppendTo[res, i]];
i += 2;
];
res
- Output:
{6,12,20,24,28,30,40,42,48,54,56,60,66,70,78,80,84,88,90,96,102,104,108,112,114,120,126,132,138,140,150,156,160,168,174,176,180,186,192,198,204,208,210,216,220,222,224,228,234,240,246,252,258,260,264,270,272,276,280,282,294,300,304,306,308,312,318,320,330,336,340,342,348,350,352,354,360,364,366,368,372,378,380,384,390,396,402,408,414,416,420,426,432,438,440,444,448,456,460,462,464,468,474,476,480,486,490,492,496,498,500,504,510,516,520,522,528,532,534,540,544,546,550,552,558,560,564,570,572,580,582,588,594,600,606,608,612,616,618,620,624,630,636,640,642,644,650,654,660,666,672,678,680,684,690,696,700,702,704,708,714,720,726,728,732,736,740,744,750,756,760,762,768,770,780,786,792,798,804,810,812,816,820,822,828,832,834,836,840,852,858,860,864,868,870,876,880,888,894,896,906,910,912,918,920,924,928,930,936,940,942,945,948,952,960,966,972,978,980,984} {945,1575,2205,2835,3465,4095,4725,5355,5775,5985,6435,6615,6825,7245,7425,7875,8085,8415,8505,8925,9135,9555,9765,10395,11655,12285,12705,12915,13545,14175,14805,15015,15435,16065,16695,17325,17955,18585,19215,19305}
Nim
import math, strutils
template isEven(n: int): bool = (n and 1) == 0
template isOdd(n: int): bool = (n and 1) != 0
func getDivisors(n: int): seq[int] =
result = @[1, n]
for i in 2..sqrt(n.toFloat).int:
if n mod i == 0:
let j = n div i
result.add i
if i != j: result.add j
func isPartSum(divs: seq[int]; sum: int): bool =
if sum == 0: return true
if divs.len == 0: return false
let last = divs[^1]
let divs = divs[0..^2]
result = isPartSum(divs, sum)
if not result and last <= sum:
result = isPartSum(divs, sum - last)
func isZumkeller(n: int): bool =
let divs = n.getDivisors()
let sum = sum(divs)
# If "sum" is odd, it can't be split into two partitions with equal sums.
if sum.isOdd: return false
# If "n" is odd use "abundant odd number" optimization.
if n.isOdd:
let abundance = sum - 2 * n
return abundance > 0 and abundance.isEven
# If "n" and "sum" are both even, check if there's a partition which totals "sum / 2".
result = isPartSum(divs, sum div 2)
when isMainModule:
echo "The first 220 Zumkeller numbers are:"
var n = 2
var count = 0
while count < 220:
if n.isZumkeller:
stdout.write align($n, 3)
inc count
stdout.write if count mod 20 == 0: '\n' else: ' '
inc n
echo()
echo "The first 40 odd Zumkeller numbers are:"
n = 3
count = 0
while count < 40:
if n.isZumkeller:
stdout.write align($n, 5)
inc count
stdout.write if count mod 10 == 0: '\n' else: ' '
inc n, 2
echo()
echo "The first 40 odd Zumkeller numbers which don't end in 5 are:"
n = 3
count = 0
while count < 40:
if n mod 10 != 5 and n.isZumkeller:
stdout.write align($n, 7)
inc count
stdout.write if count mod 8 == 0: '\n' else: ' '
inc n, 2
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
PARI/GP
\\ Define a function to check if a number is Zumkeller
isZumkeller(n) = {
my(d = divisors(n));
my(ds = sum(i=1, #d, d[i])); \\ Total of divisors
if (ds % 2, return(0)); \\ If sum of divisors is odd, return false
my(coeffs = vector(ds+1, i, 0)); \\ Create a vector to store coefficients
coeffs[1] = 1;
for(i=1, #d, coeffs = Pol(coeffs) * (1 + x^d[i]); coeffs = Vecrev(coeffs); if(#coeffs > ds + 1, coeffs = coeffs[^1])); \\ Generate coefficients
coeffs[ds \ 2 + 1] > 0; \\ Check if the middle coefficient is positive
}
\\ Generate a list of Zumkeller numbers
ZumkellerList(limit) = {
my(res = List(), i = 1);
while(#res < limit,
if(isZumkeller(i), listput(res, i));
i++;
);
Vec(res); \\ Convert list to vector
}
\\ Generate a list of odd Zumkeller numbers
OddZumkellerList(limit) = {
my(res = List(), i = 1);
while(#res < limit,
if(isZumkeller(i), listput(res, i));
i += 2; \\ Only check odd numbers
);
Vec(res); \\ Convert list to vector
}
\\ Call the functions to get the lists
zumkeller220 = ZumkellerList(220);
oddZumkeller40 = OddZumkellerList(40);
\\ Print the results
print(zumkeller220);
print(oddZumkeller40);
- Output:
[6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96, 102, 104, 108, 112, 114, 120, 126, 132, 138, 140, 150, 156, 160, 168, 174, 176, 180, 186, 192, 198, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252, 258, 260, 264, 270, 272, 276, 280, 282, 294, 300, 304, 306, 308, 312, 318, 320, 330, 336, 340, 342, 348, 350, 352, 354, 360, 364, 366, 368, 372, 378, 380, 384, 390, 396, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 456, 460, 462, 464, 468, 474, 476, 480, 486, 490, 492, 496, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552, 558, 560, 564, 570, 572, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 650, 654, 660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 740, 744, 750, 756, 760, 762, 768, 770, 780, 786, 792, 798, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 852, 858, 860, 864, 868, 870, 876, 880, 888, 894, 896, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 960, 966, 972, 978, 980, 984] [945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305]
Pascal
Using sieve for primedecomposition
Now using the trick, that one partition sum must include n and improved recursive search.
Limit is ~1.2e11
program zumkeller;
//https://oeis.org/A083206/a083206.txt
{$IFDEF FPC}
{$MODE DELPHI} {$OPTIMIZATION ON,ALL} {$COPERATORS ON}
// {$O+,I+}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
sysutils
{$IFDEF WINDOWS},Windows{$ENDIF}
;
//######################################################################
//prime decomposition
const
//HCN(86) > 1.2E11 = 128,501,493,120 count of divs = 4096 7 3 1 1 1 1 1 1 1
HCN_DivCnt = 4096;
//stop never ending recursion
RECCOUNTMAX = 100*1000*1000;
DELTAMAX = 1000*1000;
type
tItem = Uint64;
tDivisors = array [0..HCN_DivCnt-1] of tItem;
tpDivisor = pUint64;
const
SizePrDeFe = 12697;//*72 <= 1 or 2 Mb ~ level 2 cache -32kB for DIVS
type
tdigits = packed record
dgtDgts : array [0..31] of Uint32;
end;
//the first number with 11 different divisors =
// 2*3*5*7*11*13*17*19*23*29*31 = 2E11
tprimeFac = packed record
pfSumOfDivs,
pfRemain : Uint64; //n div (p[0]^[pPot[0] *...) can handle primes <=821641^2 = 6.7e11
pfpotPrim : array[0..9] of UInt32;//+10*4 = 56 Byte
pfpotMax : array[0..9] of byte; //10 = 66
pfMaxIdx : Uint16; //68
pfDivCnt : Uint32; //72
end;
tPrimeDecompField = array[0..SizePrDeFe-1] of tprimeFac;
tPrimes = array[0..65535] of Uint32;
var
SmallPrimes: tPrimes;
//######################################################################
//prime decomposition
procedure InitSmallPrimes;
//only odd numbers
const
MAXLIMIT = (821641-1) shr 1;
var
pr : array[0..MAXLIMIT] of byte;
p,j,d,flipflop :NativeUInt;
Begin
SmallPrimes[0] := 2;
fillchar(pr[0],SizeOf(pr),#0);
p := 0;
repeat
repeat
p +=1
until pr[p]= 0;
j := (p+1)*p*2;
if j>MAXLIMIT then
BREAK;
d := 2*p+1;
repeat
pr[j] := 1;
j += d;
until j>MAXLIMIT;
until false;
SmallPrimes[1] := 3;
SmallPrimes[2] := 5;
j := 3;
d := 7;
flipflop := 3-1;
p := 3;
repeat
if pr[p] = 0 then
begin
SmallPrimes[j] := d;
inc(j);
end;
d += 2*flipflop;
p+=flipflop;
flipflop := 3-flipflop;
until (p > MAXLIMIT) OR (j>High(SmallPrimes));
end;
function OutPots(const pD:tprimeFac;n:NativeInt):Ansistring;
var
s: String[31];
Begin
str(n,s);
result := s+' :';
with pd do
begin
str(pfDivCnt:3,s);
result += s+' : ';
For n := 0 to pfMaxIdx-1 do
Begin
if n>0 then
result += '*';
str(pFpotPrim[n],s);
result += s;
if pfpotMax[n] >1 then
Begin
str(pfpotMax[n],s);
result += '^'+s;
end;
end;
If pfRemain >1 then
Begin
str(pfRemain,s);
result += '*'+s;
end;
str(pfSumOfDivs,s);
result += '_SoD_'+s+'<';
end;
end;
function CnvtoBASE(var dgt:tDigits;n:Uint64;base:NativeUint):NativeInt;
//n must be multiple of base
var
q,r: Uint64;
i : NativeInt;
Begin
with dgt do
Begin
fillchar(dgtDgts,SizeOf(dgtDgts),#0);
i := 0;
// dgtNum:= n;
n := n div base;
result := 0;
repeat
r := n;
q := n div base;
r -= q*base;
n := q;
dgtDgts[i] := r;
inc(i);
until (q = 0);
result := 0;
while (result<i) AND (dgtDgts[result] = 0) do
inc(result);
inc(result);
end;
end;
function IncByBaseInBase(var dgt:tDigits;base:NativeInt):NativeInt;
var
q :NativeInt;
Begin
with dgt do
Begin
result := 0;
q := dgtDgts[result]+1;
// inc(dgtNum,base);
if q = base then
begin
repeat
dgtDgts[result] := 0;
inc(result);
q := dgtDgts[result]+1;
until q <> base;
end;
dgtDgts[result] := q;
result +=1;
end;
end;
procedure SieveOneSieve(var pdf:tPrimeDecompField;n:nativeUInt);
var
dgt:tDigits;
i, j, k,pr,fac : NativeUInt;
begin
//init
for i := 0 to High(pdf) do
with pdf[i] do
Begin
pfDivCnt := 1;
pfSumOfDivs := 1;
pfRemain := n+i;
pfMaxIdx := 0;
end;
//first 2 make n+i even
i := n AND 1;
repeat
with pdf[i] do
if n+i > 0 then
begin
j := BsfQWord(n+i);
pfMaxIdx := 1;
pfpotPrim[0] := 2;
pfpotMax[0] := j;
pfRemain := (n+i) shr j;
pfSumOfDivs := (1 shl (j+1))-1;
pfDivCnt := j+1;
end;
i += 2;
until i >High(pdf);
// i now index in SmallPrimes
i := 0;
repeat
//search next prime that is in bounds of sieve
repeat
inc(i);
if i >= High(SmallPrimes) then
BREAK;
pr := SmallPrimes[i];
k := pr-n MOD pr;
if (k = pr) AND (n>0) then
k:= 0;
if k < SizePrDeFe then
break;
until false;
if i >= High(SmallPrimes) then
BREAK;
//no need to use higher primes
if pr*pr > n+SizePrDeFe then
BREAK;
// j is power of prime
j := CnvtoBASE(dgt,n+k,pr);
repeat
with pdf[k] do
Begin
pfpotPrim[pfMaxIdx] := pr;
pfpotMax[pfMaxIdx] := j;
pfDivCnt *= j+1;
fac := pr;
repeat
pfRemain := pfRemain DIV pr;
dec(j);
fac *= pr;
until j<= 0;
pfSumOfDivs *= (fac-1)DIV(pr-1);
inc(pfMaxIdx);
end;
k += pr;
j := IncByBaseInBase(dgt,pr);
until k >= SizePrDeFe;
until false;
//correct sum of & count of divisors
for i := 0 to High(pdf) do
Begin
with pdf[i] do
begin
j := pfRemain;
if j <> 1 then
begin
pfSumOFDivs *= (j+1);
pfDivCnt *=2;
end;
end;
end;
end;
//prime decomposition
//######################################################################
procedure Init_Check_rec(const pD:tprimeFac;var Divs,SumOfDivs:tDivisors);forward;
var
{$ALIGN 32}
PrimeDecompField:tPrimeDecompField;
{$ALIGN 32}
Divs :tDivisors;
SumOfDivs : tDivisors;
DivUsedIdx : tDivisors;
pDiv :tpDivisor;
T0: Int64;
count,rec_Cnt: NativeInt;
depth : Int32;
finished :Boolean;
procedure Check_rek_depth(SoD : Int64;i: NativeInt);
var
sum : Int64;
begin
if finished then
EXIT;
inc(rec_Cnt);
WHILE (i>0) AND (pDiv[i]>SoD) do
dec(i);
while i >= 0 do
Begin
DivUsedIdx[depth] := pDiv[i];
sum := SoD-pDiv[i];
if sum = 0 then
begin
finished := true;
EXIT;
end;
dec(i);
inc(depth);
if (i>= 0) AND (sum <= SumOfDivs[i]) then
Check_rek_depth(sum,i);
if finished then
EXIT;
// DivUsedIdx[depth] := 0;
dec(depth);
end;
end;
procedure Out_One_Sol(const pd:tprimefac;n:NativeUInt;isZK : Boolean);
var
sum : NativeInt;
Begin
if n< 7 then
exit;
with pd do
begin
writeln(OutPots(pD,n));
if isZK then
Begin
Init_Check_rec(pD,Divs,SumOfDivs);
Check_rek_depth(pfSumOfDivs shr 1-n,pFDivCnt-1);
write(pfSumOfDivs shr 1:10,' = ');
sum := n;
while depth >= 0 do
Begin
sum += DivUsedIdx[depth];
write(DivUsedIdx[depth],'+');
dec(depth);
end;
write(n,' = ',sum);
end
else
write(' no zumkeller ');
end;
end;
procedure InsertSort(pDiv:tpDivisor; Left, Right : NativeInt );
var
I, J: NativeInt;
Pivot : tItem;
begin
for i:= 1 + Left to Right do
begin
Pivot:= pDiv[i];
j:= i - 1;
while (j >= Left) and (pDiv[j] > Pivot) do
begin
pDiv[j+1]:=pDiv[j];
Dec(j);
end;
pDiv[j+1]:= pivot;
end;
end;
procedure GetDivs(const pD:tprimeFac;var Divs,SumOfDivs:tDivisors);
var
pDivs : tpDivisor;
pPot : UInt64;
i,len,j,l,p,k: Int32;
Begin
i := pD.pfDivCnt;
pDivs := @Divs[0];
pDivs[0] := 1;
len := 1;
l := 1;
with pD do
Begin
For i := 0 to pfMaxIdx-1 do
begin
//Multiply every divisor before with the new primefactors
//and append them to the list
k := pfpotMax[i];
p := pfpotPrim[i];
pPot :=1;
repeat
pPot *= p;
For j := 0 to len-1 do
Begin
pDivs[l]:= pPot*pDivs[j];
inc(l);
end;
dec(k);
until k<=0;
len := l;
end;
p := pfRemain;
If p >1 then
begin
For j := 0 to len-1 do
Begin
pDivs[l]:= p*pDivs[j];
inc(l);
end;
len := l;
end;
end;
//Sort. Insertsort much faster than QuickSort in this special case
InsertSort(pDivs,0,len-1);
pPot := 0;
For i := 0 to len-1 do
begin
pPot += pDivs[i];
SumOfDivs[i] := pPot;
end;
end;
procedure Init_Check_rec(const pD:tprimeFac;var Divs,SumOfDivs:tDivisors);
begin
GetDivs(pD,Divs,SUmOfDivs);
finished := false;
depth := 0;
pDiv := @Divs[0];
end;
procedure Check_rek(SoD : Int64;i: NativeInt);
var
sum : Int64;
begin
if finished then
EXIT;
if rec_Cnt >RECCOUNTMAX then
begin
rec_Cnt := -1;
finished := true;
exit;
end;
inc(rec_Cnt);
WHILE (i>0) AND (pDiv[i]>SoD) do
dec(i);
while i >= 0 do
Begin
sum := SoD-pDiv[i];
if sum = 0 then
begin
finished := true;
EXIT;
end;
dec(i);
if (i>= 0) AND (sum <= SumOfDivs[i]) then
Check_rek(sum,i);
if finished then
EXIT;
end;
end;
function GetZumKeller(n: NativeUint;var pD:tPrimefac): boolean;
var
SoD,sum : Int64;
Div_cnt,i,pracLmt: NativeInt;
begin
rec_Cnt := 0;
SoD:= pd.pfSumOfDivs;
//sum must be even and n not deficient
if Odd(SoD) or (SoD<2*n) THEN
EXIT(false);
//if Odd(n) then Exit(Not(odd(sum)));// to be tested
SoD := SoD shr 1-n;
If SoD < 2 then //0,1 is always true
Exit(true);
Div_cnt := pD.pfDivCnt;
if Not(odd(n)) then
if ((n mod 18) in [6,12]) then
EXIT(true);
//Now one needs to get the divisors
Init_check_rec(pD,Divs,SumOfDivs);
pracLmt:= 0;
if Not(odd(n)) then
begin
For i := 1 to Div_Cnt do
Begin
sum := SumOfDivs[i];
If (sum+1<Divs[i+1]) AND (sum<SoD) then
Begin
pracLmt := i;
BREAK;
end;
IF (sum>=SoD) then break;
end;
if pracLmt = 0 then
Exit(true);
end;
//number is practical followed by one big prime
if pracLmt = (Div_Cnt-1) shr 1 then
begin
i := SoD mod Divs[pracLmt+1];
with pD do
begin
if pfRemain > 1 then
EXIT((pfRemain<=i) OR (i<=sum))
else
EXIT((pfpotPrim[pfMaxIdx-1]<=i)OR (i<=sum));
end;
end;
Begin
IF Div_cnt <= HCN_DivCnt then
Begin
Check_rek(SoD,Div_cnt-1);
IF rec_Cnt = -1 then
exit(true);
exit(finished);
end;
end;
result := false;
end;
var
Ofs,i,n : NativeUInt;
Max: NativeUInt;
procedure Init_Sieve(n:NativeUint);
//Init Sieve i,oFs are Global
begin
i := n MOD SizePrDeFe;
Ofs := (n DIV SizePrDeFe)*SizePrDeFe;
SieveOneSieve(PrimeDecompField,Ofs);
end;
procedure GetSmall(MaxIdx:Int32);
var
ZK: Array of Uint32;
idx: UInt32;
Begin
If MaxIdx<1 then
EXIT;
writeln('The first ',MaxIdx,' zumkeller numbers');
Init_Sieve(0);
setlength(ZK,MaxIdx);
idx := Low(ZK);
repeat
if GetZumKeller(n,PrimeDecompField[i]) then
Begin
ZK[idx] := n;
inc(idx);
end;
inc(i);
inc(n);
If i > High(PrimeDecompField) then
begin
dec(i,SizePrDeFe);
inc(ofs,SizePrDeFe);
SieveOneSieve(PrimeDecompField,Ofs);
end;
until idx >= MaxIdx;
For idx := 0 to MaxIdx-1 do
begin
if idx MOD 20 = 0 then
writeln;
write(ZK[idx]:4);
end;
setlength(ZK,0);
writeln;
writeln;
end;
procedure GetOdd(MaxIdx:Int32);
var
ZK: Array of Uint32;
idx: UInt32;
Begin
If MaxIdx<1 then
EXIT;
writeln('The first odd 40 zumkeller numbers');
n := 1;
Init_Sieve(n);
setlength(ZK,MaxIdx);
idx := Low(ZK);
repeat
if GetZumKeller(n,PrimeDecompField[i]) then
Begin
ZK[idx] := n;
inc(idx);
end;
inc(i,2);
inc(n,2);
If i > High(PrimeDecompField) then
begin
dec(i,SizePrDeFe);
inc(ofs,SizePrDeFe);
SieveOneSieve(PrimeDecompField,Ofs);
end;
until idx >= MaxIdx;
For idx := 0 to MaxIdx-1 do
begin
if idx MOD (80 DIV 8) = 0 then
writeln;
write(ZK[idx]:8);
end;
setlength(ZK,0);
writeln;
writeln;
end;
procedure GetOddNot5(MaxIdx:Int32);
var
ZK: Array of Uint32;
idx: UInt32;
Begin
If MaxIdx<1 then
EXIT;
writeln('The first odd 40 zumkeller numbers not ending in 5');
n := 1;
Init_Sieve(n);
setlength(ZK,MaxIdx);
idx := Low(ZK);
repeat
if GetZumKeller(n,PrimeDecompField[i]) then
Begin
ZK[idx] := n;
inc(idx);
end;
inc(i,2);
inc(n,2);
If n mod 5 = 0 then
begin
inc(i,2);
inc(n,2);
end;
If i > High(PrimeDecompField) then
begin
dec(i,SizePrDeFe);
inc(ofs,SizePrDeFe);
SieveOneSieve(PrimeDecompField,Ofs);
end;
until idx >= MaxIdx;
For idx := 0 to MaxIdx-1 do
begin
if idx MOD (80 DIV 8) = 0 then
writeln;
write(ZK[idx]:8);
end;
setlength(ZK,0);
writeln;
writeln;
end;
BEGIN
InitSmallPrimes;
T0 := GetTickCount64;
GetSmall(220);
GetOdd(40);
GetOddNot5(40);
writeln;
n := 1;//8996229720;//1;
Init_Sieve(n);
writeln('Start ',n,' at ',i);
T0 := GetTickCount64;
MAX := (n DIV DELTAMAX+1)*DELTAMAX;
count := 0;
repeat
writeln('Count of zumkeller numbers up to ',MAX:12);
repeat
if GetZumKeller(n,PrimeDecompField[i]) then
inc(count);
inc(i);
inc(n);
If i > High(PrimeDecompField) then
begin
dec(i,SizePrDeFe);
inc(ofs,SizePrDeFe);
SieveOneSieve(PrimeDecompField,Ofs);
end;
until n > MAX;
writeln(n-1:10,' tested found ',count:10,' ratio ',count/n:10:7);
MAX += DELTAMAX;
until MAX>10*DELTAMAX;
writeln('runtime ',(GetTickCount64-T0)/1000:8:3,' s');
writeln;
writeln('Count of recursion 59,641,327 for 8,996,229,720');
n := 8996229720;
Init_Sieve(n);
T0 := GetTickCount64;
Out_One_Sol(PrimeDecompField[i],n,true);
writeln;
writeln('runtime ',(GetTickCount64-T0)/1000:8:3,' s');
END.
- Output:
TIO.RUN The first 220 zumkeller numbers 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first odd 40 zumkeller numbers 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first odd 40 zumkeller numbers not ending in 5 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377 Start 1 at 1 Count of zumkeller numbers up to 1000000 1000000 tested found 229026 ratio 0.2290258 Count of zumkeller numbers up to 2000000 2000000 tested found 457658 ratio 0.2288289 Count of zumkeller numbers up to 3000000 3000000 tested found 686048 ratio 0.2286826 Count of zumkeller numbers up to 4000000 4000000 tested found 914806 ratio 0.2287014 Count of zumkeller numbers up to 5000000 5000000 tested found 1143521 ratio 0.2287042 Count of zumkeller numbers up to 6000000 6000000 tested found 1372208 ratio 0.2287013 Count of zumkeller numbers up to 7000000 7000000 tested found 1600977 ratio 0.2287110 Count of zumkeller numbers up to 8000000 8000000 tested found 1829932 ratio 0.2287415 Count of zumkeller numbers up to 9000000 9000000 tested found 2058883 ratio 0.2287648 Count of zumkeller numbers up to 10000000 10000000 tested found 2287889 ratio 0.2287889 runtime 1.268 s //zumkeller number with highest recursion count til 1e11 Count of recursion 59,641,327 for 8,996,229,720 8996229720 : 96 : 2^3*3^2*5*2237*11171_SoD_29253435120< 14626717560 = 36+45+60+72+90+120+180+360+201330+804312+805320+2010780+4021560+1124528715+4498114860+8996229720 = 14626717560 runtime 7.068 s // at home 9.5s Real time: 8.689 s CPU share: 98.74 % //at home til 1e11 with 85 numbers with recursion count > 1e8 9900000000 tested found 2262797501 ratio 0.2285654 recursion 10.479 runtime 48.805 s Count of zumkeller numbers up to 10000000000 rek_ -1 @ 9998443080 : 96 : 2^3*3^2*5*3041*9133_SoD_32509184760< 10000000000 tested found 2285655276 ratio 0.2285655 recursion 10.520 runtime 28.976 s real 40m7,478s user 40m7,039s sys 0m0,057s only 4 til 4,512,612,672 out_1e10.txt:104: rek_ -1 @ 584818848 : 72 : 2^5*3^2*1423*1427_SoD_1665413568< out_1e10.txt:105: rek_ -1 @ 589754016 : 72 : 2^5*3^2*1429*1433_SoD_1679457780< out_1e10.txt:174: rek_ -1 @ 1956249450 : 72 : 2*3^2*5^2*2083*2087_SoD_5260832928< out_1e10.txt:291: rek_ -1 @ 4512612672 : 84 : 2^6*3^2*2797*2801_SoD_12943833396<
Perl
use strict;
use warnings;
use feature 'say';
use ntheory <is_prime divisor_sum divisors vecsum forcomb lastfor>;
sub in_columns {
my($columns, $values) = @_;
my @v = split ' ', $values;
my $width = int(80/$columns);
printf "%${width}d"x$columns."\n", @v[$_*$columns .. -1+(1+$_)*$columns] for 0..-1+@v/$columns;
print "\n";
}
sub is_Zumkeller {
my($n) = @_;
return 0 if is_prime($n);
my @divisors = divisors($n);
return 0 unless @divisors > 2 && 0 == @divisors % 2;
my $sigma = divisor_sum($n);
return 0 unless 0 == $sigma%2 && ($sigma/2) >= $n;
if (1 == $n%2) {
return 1
} else {
my $Z = 0;
forcomb { $Z++, lastfor if vecsum(@divisors[@_]) == $sigma/2 } @divisors;
return $Z;
}
}
use constant Inf => 1e10;
say 'First 220 Zumkeller numbers:';
my $n = 0; my $z;
$z .= do { $n < 220 ? (is_Zumkeller($_) and ++$n and "$_ ") : last } for 1 .. Inf;
in_columns(20, $z);
say 'First 40 odd Zumkeller numbers:';
$n = 0; $z = '';
$z .= do { $n < 40 ? (!!($_%2) and is_Zumkeller($_) and ++$n and "$_ ") : last } for 1 .. Inf;
in_columns(10, $z);
say 'First 40 odd Zumkeller numbers not divisible by 5:';
$n = 0; $z = '';
$z .= do { $n < 40 ? (!!($_%2 and $_%5) and is_Zumkeller($_) and ++$n and "$_ ") : last } for 1 .. Inf;
in_columns(10, $z);
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not divisible by 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Phix
with javascript_semantics
function isPartSum(sequence f, integer l, t)
if t=0 then return true end if
if l=0 then return false end if
integer last = f[l]
return (t>=last and isPartSum(f, l-1, t-last))
or isPartSum(f, l-1, t)
end function
function isZumkeller(integer n)
sequence f = factors(n,1)
integer t = sum(f)
-- an odd sum cannot be split into two equal sums
if odd(t) then return false end if
-- if n is odd use 'abundant odd number' optimization
if odd(n) then
integer abundance := t - 2*n
return abundance>0 and even(abundance)
end if
-- if n and t both even check for any partition of t/2
return isPartSum(f, length(f), t/2)
end function
sequence tests = {{220,1,0,20,"%3d %n"},
{40,2,0,10,"%5d %n"},
{40,2,5,8,"%7d %n"}}
integer lim, step, rem, cr; string fmt
for t=1 to length(tests) do
{lim, step, rem, cr, fmt} = tests[t]
string o = iff(step=1?"":"odd "),
w = iff(rem=0?"":"which don't end in 5 ")
printf(1,"The first %d %sZumkeller numbers %sare:\n",{lim,o,w})
integer i = step+1, count = 0
while count<lim do
if (rem=0 or remainder(i,10)!=rem)
and isZumkeller(i) then
count += 1
printf(1,fmt,{i,remainder(count,cr)=0})
end if
i += step
end while
printf(1,"\n")
end for
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Aside: not that it really matters here, but passing an explicit length to isPartSum (ie, l) is generally quite a bit
faster than trimming (and therefore cloning) the contents of f, just so that we can rely on length(f), and obviously
that would get more significant were f much longer, though it does in fact max out at a mere 80 here.
In contrast, reversing the "or" tests on the final return of isPartSum() has a significant detrimental effect, since
it triggers a full recursive search for almost all l=0 failures before ever letting a single t=0 succeed. Quite why
I don't get anything like the same slowdown when I modify the Go code is beyond me...
PicoLisp
(de propdiv (N)
(make
(for I N
(and (=0 (% N I)) (link I)) ) ) )
(de sum? (G L)
(cond
((=0 G) T)
((= (car L) G) T)
((cdr L)
(if (> (car L) G)
(sum? G (cdr L))
(or
(sum? (- G (car L)) (cdr L))
(sum? G (cdr L)) ) ) ) ) )
(de zum? (N)
(let (L (propdiv N) S (sum prog L))
(and
(not (bit? 1 S))
(if (bit? 1 N)
(let A (- S (* 2 N))
(and (gt0 A) (not (bit? 1 A)))
)
(sum?
(- (/ S 2) (car L))
(cdr L) ) ) ) ) )
(zero C)
(for (I 2 (> 220 C) (inc I))
(when (zum? I)
(prin (align 3 I) " ")
(inc 'C)
(and
(=0 (% C 20))
(prinl) ) ) )
(prinl)
(zero C)
(for (I 1 (> 40 C) (inc 'I 2))
(when (zum? I)
(prin (align 9 I) " ")
(inc 'C)
(and
(=0 (% C 8))
(prinl) ) ) )
(prinl)
(zero C)
# cheater
(for (I 81079 (> 40 C) (inc 'I 2))
(when (and (<> 5 (% I 10)) (zum? I))
(prin (align 9 I) " ")
(inc 'C)
(and
(=0 (% C 8))
(prinl) ) ) )
- Output:
6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Python
Procedural
Modified from a footnote at OEIS A083207 (see reference in problem text) by Charles R Greathouse IV.
from sympy import divisors
from sympy.combinatorics.subsets import Subset
def isZumkeller(n):
d = divisors(n)
s = sum(d)
if not s % 2 and max(d) <= s/2:
for x in range(1, 2**len(d)):
if sum(Subset.unrank_binary(x, d).subset) == s/2:
return True
return False
def printZumkellers(N, oddonly=False):
nprinted = 0
for n in range(1, 10**5):
if (oddonly == False or n % 2) and isZumkeller(n):
print(f'{n:>8}', end='')
nprinted += 1
if nprinted % 10 == 0:
print()
if nprinted >= N:
return
print("220 Zumkeller numbers:")
printZumkellers(220)
print("\n\n40 odd Zumkeller numbers:")
printZumkellers(40, True)
- Output:
220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
Functional
Relying on the standard Python libraries, as an alternative to importing SymPy:
'''Zumkeller numbers'''
from itertools import (
accumulate, chain, count, groupby, islice, product
)
from functools import reduce
from math import floor, sqrt
import operator
# ---------------------- ZUMKELLER -----------------------
# isZumkeller :: Int -> Bool
def isZumkeller(n):
'''True if there exists a disjoint partition
of the divisors of m, such that the two sets have
the same sum.
(In other words, if n is in OEIS A083207)
'''
ds = divisors(n)
m = sum(ds)
if even(m):
half = m // 2
return half in ds or (
all(map(ge(half), ds)) and (
summable(half, ds)
)
)
else:
return False
# summable :: Int -> [Int] -> Bool
def summable(x, xs):
'''True if any subset of the sorted
list xs sums to x.
'''
if xs:
if x in xs:
return True
else:
t = xs[1:]
return summable(x - xs[0], t) or summable(x, t)
else:
return False
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''First 220 Zumkeller numbers,
and first 40 odd Zumkellers.
'''
tenColumns = tabulated(10)
print('First 220 Zumkeller numbers:\n')
print(tenColumns(
take(220)(
filter(isZumkeller, count(1))
)
))
print('\nFirst 40 odd Zumkeller numbers:\n')
print(tenColumns(
take(40)(
filter(isZumkeller, enumFromThen(1)(3))
)
))
# ---------------------- TABULATION ----------------------
# tabulated :: Int -> [a] -> String
def tabulated(nCols):
'''String representation of a list
of values as rows of n columns.
'''
def go(xs):
ts = [str(x) for x in xs]
w = 1 + max(len(x) for x in ts)
return '\n'.join([
''.join(row) for row
in chunksOf(nCols)([
t.rjust(w, ' ') for t in ts
])
])
return go
# ----------------------- GENERIC ------------------------
# chunksOf :: Int -> [a] -> [[a]]
def chunksOf(n):
'''A series of lists of length n, subdividing the
contents of xs. Where the length of xs is not evenly
divible, the final list will be shorter than n.
'''
def go(xs):
return (
xs[i:n + i] for i in range(0, len(xs), n)
) if 0 < n else None
return go
# divisors :: Int -> [Int]
def divisors(n):
'''The ordered divisors of n.
'''
def go(a, x):
return [a * b for a, b in product(
a,
accumulate(chain([1], x), operator.mul)
)]
return sorted(
reduce(go, [
list(g) for _, g in groupby(primeFactors(n))
], [1])
) if 1 < n else [1]
# enumFromThen :: Int -> Int -> [Int]
def enumFromThen(m):
'''A non-finite stream of integers
starting at m, and continuing
at the interval between m and n.
'''
return lambda n: count(m, n - m)
# even :: Int -> Bool
def even(x):
'''True if x is an integer
multiple of two.
'''
return 0 == x % 2
# ge :: Eq a => a -> a -> Bool
def ge(a):
def go(b):
return operator.ge(a, b)
return go
# primeFactors :: Int -> [Int]
def primeFactors(n):
'''A list of the prime factors of n.
'''
def f(qr):
r = qr[1]
return step(r), 1 + r
def step(x):
return 1 + (x << 2) - ((x >> 1) << 1)
def go(x):
root = floor(sqrt(x))
def p(qr):
q = qr[0]
return root < q or 0 == (x % q)
q = until(p)(f)(
(2 if 0 == x % 2 else 3, 1)
)[0]
return [x] if q > root else [q] + go(x // q)
return go(n)
# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
'''The prefix of xs of length n,
or xs itself if n > length xs.
'''
def go(xs):
return (
xs[0:n]
if isinstance(xs, (list, tuple))
else list(islice(xs, n))
)
return go
# until :: (a -> Bool) -> (a -> a) -> a -> a
def until(p):
'''The result of repeatedly applying f until p holds.
The initial seed value is x.
'''
def go(f):
def g(x):
v = x
while not p(v):
v = f(v)
return v
return g
return go
# MAIN ---
if __name__ == '__main__':
main()
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305
Racket
#lang racket
(require math/number-theory)
(define (zum? n)
(let* ((set (divisors n))
(sum (apply + set)))
(cond
[(odd? sum) #f]
[(odd? n) ; if n is odd use 'abundant odd number' optimization
(let ((abundance (- sum (* n 2)))) (and (positive? abundance) (even? abundance)))]
[else
(let ((sum/2 (quotient sum 2)))
(let loop ((acc (car set)) (set (cdr set)))
(cond [(= acc sum/2) #t]
[(> acc sum/2) #f]
[(null? set) #f]
[else (or (loop (+ (car set) acc) (cdr set))
(loop acc (cdr set)))])))])))
(define (first-n-matching-naturals count pred)
(for/list ((i count) (j (stream-filter pred (in-naturals 1)))) j))
(define (tabulate title ns (row-width 132))
(displayln title)
(let* ((cell-width (+ 2 (order-of-magnitude (apply max ns))))
(cells/row (quotient row-width cell-width)))
(let loop ((ns ns) (col cells/row))
(cond [(null? ns) (unless (= col cells/row) (newline))]
[(zero? col) (newline) (loop ns cells/row)]
[else (display (~a #:width cell-width #:align 'right (car ns)))
(loop (cdr ns) (sub1 col))]))))
(tabulate "First 220 Zumkeller numbers:" (first-n-matching-naturals 220 zum?))
(newline)
(tabulate "First 40 odd Zumkeller numbers:"
(first-n-matching-naturals 40 (λ (n) (and (odd? n) (zum? n)))))
(newline)
(tabulate "First 40 odd Zumkeller numbers not ending in 5:"
(first-n-matching-naturals 40 (λ (n) (and (odd? n) (not (= 5 (modulo n 10))) (zum? n)))))
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not ending in 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Raku
(formerly Perl 6)
use ntheory:from<Perl5> <factor is_prime>;
sub zumkeller ($range) {
$range.grep: -> $maybe {
next if $maybe < 3 or $maybe.&is_prime;
my @divisors = $maybe.&factor.combinations».reduce( &[×] ).unique.reverse;
next unless [and] @divisors > 2, @divisors %% 2, (my $sum = @divisors.sum) %% 2, ($sum /= 2) ≥ $maybe;
my $zumkeller = False;
if $maybe % 2 {
$zumkeller = True
} else {
TEST: for 1 ..^ @divisors/2 -> $c {
@divisors.combinations($c).map: -> $d {
next if $d.sum != $sum;
$zumkeller = True and last TEST
}
}
}
$zumkeller
}
}
say "First 220 Zumkeller numbers:\n" ~
zumkeller(^Inf)[^220].rotor(20)».fmt('%3d').join: "\n";
put "\nFirst 40 odd Zumkeller numbers:\n" ~
zumkeller((^Inf).map: * × 2 + 1)[^40].rotor(10)».fmt('%7d').join: "\n";
# Stretch. Slow to calculate. (minutes)
put "\nFirst 40 odd Zumkeller numbers not divisible by 5:\n" ~
zumkeller(flat (^Inf).map: {my \p = 10 * $_; p+1, p+3, p+7, p+9} )[^40].rotor(10)».fmt('%7d').join: "\n";
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not divisible by 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
REXX
The construction of the partitions were created in the order in which the most likely partitions would match.
/*REXX pgm finds & shows Zumkeller numbers: 1st N; 1st odd M; 1st odd V not ending in 5.*/
parse arg n m v . /*obtain optional arguments from the CL*/
if n=='' | n=="," then n= 220 /*Not specified? Then use the default.*/
if m=='' | m=="," then m= 40 /* " " " " " " */
if v=='' | v=="," then v= 40 /* " " " " " " */
@zum= ' Zumkeller numbers are: ' /*literal used for displaying messages.*/
sw= linesize() - 1 /*obtain the usable screen width. */
say
if n>0 then say center(' The first ' n @zum, sw, "═")
#= 0 /*the count of Zumkeller numbers so far*/
$= /*initialize the $ list (to a null).*/
do j=1 until #==n /*traipse through integers 'til done. */
if \Zum(j) then iterate /*if not a Zumkeller number, then skip.*/
#= # + 1; call add$ /*bump Zumkeller count; add to $ list.*/
end /*j*/
if $\=='' then say $ /*Are there any residuals? Then display*/
say
if m>0 then say center(' The first odd ' m @zum, sw, "═")
#= 0 /*the count of Zumkeller numbers so far*/
$= /*initialize the $ list (to a null).*/
do j=1 by 2 until #==m /*traipse through integers 'til done. */
if \Zum(j) then iterate /*if not a Zumkeller number, then skip.*/
#= # + 1; call add$ /*bump Zumkeller count; add to $ list.*/
end /*j*/
if $\=='' then say $ /*Are there any residuals? Then display*/
say
if v>0 then say center(' The first odd ' v " (not ending in 5) " @zum, sw, '═')
#= 0 /*the count of Zumkeller numbers so far*/
$= /*initialize the $ list (to a null).*/
do j=1 by 2 until #==v /*traipse through integers 'til done. */
if right(j,1)==5 then iterate /*skip if odd number ends in digit "5".*/
if \Zum(j) then iterate /*if not a Zumkeller number, then skip.*/
#= # + 1; call add$ /*bump Zumkeller count; add to $ list.*/
end /*j*/
if $\=='' then say $ /*Are there any residuals? Then display*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
add$: _= strip($ j, 'L'); if length(_)<sw then do; $= _; return; end /*add to $*/
say strip($, 'L'); $= j; return /*say, add*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
iSqrt: procedure; parse arg x; r= 0; q= 1; do while q<=x; q=q*4; end
do while q>1; q= q%4; _= x-r-q; r= r%2; if _>=0 then do; x= _; r= r+q; end; end
return r /*R is the integer square root of X. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
PDaS: procedure; parse arg x 1 b; odd= x//2 /*obtain X and B (the 1st argument).*/
if x==1 then return 1 1 /*handle special case for unity. */
r= iSqrt(x) /*calculate integer square root of X. */
a= 1 /* [↓] use all, or only odd numbers. */
sig= a + b /*initialize the sigma (so far) ___ */
do j=2+odd by 1+odd to r - (r*r==x) /*divide by some integers up to √ X */
if x//j==0 then do; a=a j; b= x%j b /*if ÷, add both divisors to α & ß. */
sig= sig +j +x%j /*bump the sigma (the sum of divisors).*/
end
end /*j*/ /* [↑] % is the REXX integer division*/
/* [↓] adjust for a square. ___*/
if j*j==x then return sig+j a j b /*Was X a square? If so, add √ X */
return sig a b /*return the divisors (both lists). */
/*──────────────────────────────────────────────────────────────────────────────────────*/
Zum: procedure; parse arg x . /*obtain a # to be tested for Zumkeller*/
if x<6 then return 0 /*test if X is too low " " */
if x<945 then if x//2==1 then return 0 /* " " " " " " for odd " */
parse value PDaS(x) with sigma pdivs /*obtain sigma and the proper divisors.*/
if sigma//2 then return 0 /*Is the sigma odd? Not Zumkeller.*/
#= words(pdivs) /*count the number of divisors for X. */
if #<3 then return 0 /*Not enough divisors? " " */
if x//2 then do; _= sigma - x - x /*use abundant optimization for odd #'s*/
return _>0 & _//2==0 /*Abundant is > 0 and even? It's a Zum*/
end
if #>23 then return 1 /*# divisors is 24 or more? It's a Zum*/
do i=1 for #; @.i= word(pdivs, i) /*assign proper divisors to the @ array*/
end /*i*/
c=0; u= 2**#; !.= .
do p=1 for u-2; b= x2b(d2x(p)) /*convert P──►binary with leading zeros*/
b= right(strip(b, 'L', 0), #, 0) /*ensure enough leading zeros for B. */
r= reverse(b); if !.r\==. then iterate /*is this binary# a palindrome of prev?*/
c= c + 1; yy.c= b; !.b= /*store this particular combination. */
end /*p*/
do part=1 for c; p1= 0; p2= 0 /*test of two partitions add to same #.*/
_= yy.part /*obtain one method of partitioning. */
do cp=1 for # /*obtain the sums of the two partitions*/
if substr(_, cp, 1) then p1= p1 + @.cp /*if a one, then add it to P1.*/
else p2= p2 + @.cp /* " " zero, " " " " P2.*/
end /*cp*/
if p1==p2 then return 1 /*Partition sums equal? Then X is Zum.*/
end /*part*/
return 0 /*no partition sum passed. X isn't Zum*/
- output when using the default inputs:
══════════════════════════════════════════════ The first 220 Zumkeller numbers are: ═══════════════════════════════════════════════ 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 ═════════════════════════════════════════════ The first odd 40 Zumkeller numbers are: ═════════════════════════════════════════════ 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 ═══════════════════════════════════ The first odd 40 (not ending in 5) Zumkeller numbers are: ═══════════════════════════════════ 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Ring
load "stdlib.ring"
see "working..." + nl
see "The first 220 Zumkeller numbers are:" + nl
permut = []
zumind = []
zumodd = []
limit = 19305
num1 = 0
num2 = 0
for n = 2 to limit
zumkeller = []
zumList = []
permut = []
calmo = []
zumind = []
num = 0
nold = 0
for m = 1 to n
if n % m = 0
num = num + 1
add(zumind,m)
ok
next
for p = 1 to num
add(zumList,1)
add(zumList,2)
next
permut(zumList)
lenZum = len(zumList)
for n2 = 1 to len(permut)/lenZum
str = ""
for m = (n2-1)*lenZum+1 to n2*lenZum
str = str + string(permut[m])
next
if str != ""
strNum = number(str)
add(calmo,strNum)
ok
next
calmo = sort(calmo)
for x = len(calmo) to 2 step -1
if calmo[x] = calmo[x-1]
del(calmo,x)
ok
next
zumkeller = []
calmoLen = len(string(calmo[1]))
calmoLen2 = calmoLen/2
for y = 1 to len(calmo)
tmpStr = string(calmo[y])
tmp1 = left(tmpStr,calmoLen2)
tmp2 = number(tmp1)
add(zumkeller,tmp2)
next
zumkeller = sort(zumkeller)
for x = len(zumkeller) to 2 step -1
if zumkeller[x] = zumkeller[x-1]
del(zumkeller,x)
ok
next
for z = 1 to len(zumkeller)
zumsum1 = 0
zumsum2 = 0
zum1 = []
zum2 = []
for m = 1 to len(string(zumkeller[z]))
zumstr = string(zumkeller[z])
tmp = number(zumstr[m])
if tmp = 1
add(zum1,zumind[m])
else
add(zum2,zumind[m])
ok
next
for z1 = 1 to len(zum1)
zumsum1 = zumsum1 + zum1[z1]
next
for z2 = 1 to len(zum2)
zumsum2 = zumsum2 + zum2[z2]
next
if zumsum1 = zumsum2
num1 = num1 + 1
if n != nold
if num1 < 221
if (n-1)%22 = 0
see nl + " " + n
else
see " " + n
ok
ok
if zumsum1%2 = 1
num2 = num2 + 1
if num2 < 41
add(zumodd,n)
ok
ok
ok
nold = n
ok
next
next
see "The first 40 odd Zumkeller numbers are:" + nl
for n = 1 to len(zumodd)
if (n-1)%8 = 0
see nl + " " + zumodd[n]
else
see " " + zumodd[n]
ok
next
see nl + "done..." + nl
func permut(list)
for perm = 1 to factorial(len(list))
for i = 1 to len(list)
add(permut,list[i])
next
perm(list)
next
func perm(a)
elementcount = len(a)
if elementcount < 1
return
ok
pos = elementcount-1
while a[pos] >= a[pos+1]
pos -= 1
if pos <= 0 permutationReverse(a, 1, elementcount)
return
ok
end
last = elementcount
while a[last] <= a[pos]
last -= 1
end
temp = a[pos]
a[pos] = a[last]
a[last] = temp
permReverse(a, pos+1, elementcount)
func permReverse(a,first,last)
while first < last
temp = a[first]
a[first] = a[last]
a[last] = temp
first += 1
last -= 1
end
Output:
working... The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 done...
Ruby
class Integer
def divisors
res = [1, self]
(2..Integer.sqrt(self)).each do |n|
div, mod = divmod(n)
res << n << div if mod.zero?
end
res.uniq.sort
end
def zumkeller?
divs = divisors
sum = divs.sum
return false unless sum.even? && sum >= self*2
half = sum / 2
max_combi_size = divs.size / 2
1.upto(max_combi_size).any? do |combi_size|
divs.combination(combi_size).any?{|combi| combi.sum == half}
end
end
end
def p_enum(enum, cols = 10, col_width = 8)
enum.each_slice(cols) {|slice| puts "%#{col_width}d"*slice.size % slice}
end
puts "#{n=220} Zumkeller numbers:"
p_enum 1.step.lazy.select(&:zumkeller?).take(n), 14, 6
puts "\n#{n=40} odd Zumkeller numbers:"
p_enum 1.step(by: 2).lazy.select(&:zumkeller?).take(n)
puts "\n#{n=40} odd Zumkeller numbers not ending with 5:"
p_enum 1.step(by: 2).lazy.select{|x| x % 5 > 0 && x.zumkeller?}.take(n)
- Output:
220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 40 odd Zumkeller numbers not ending with 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Rust
use std::convert::TryInto;
/// Gets all divisors of a number, including itself
fn get_divisors(n: u32) -> Vec<u32> {
let mut results = Vec::new();
for i in 1..(n / 2 + 1) {
if n % i == 0 {
results.push(i);
}
}
results.push(n);
results
}
/// Calculates whether the divisors can be partitioned into two disjoint
/// sets that sum to the same value
fn is_summable(x: i32, divisors: &[u32]) -> bool {
if !divisors.is_empty() {
if divisors.contains(&(x as u32)) {
return true;
} else if let Some((first, t)) = divisors.split_first() {
return is_summable(x - *first as i32, &t) || is_summable(x, &t);
}
}
false
}
/// Calculates whether the number is a Zumkeller number
/// Zumkeller numbers are the set of numbers whose divisors can be partitioned
/// into two disjoint sets that sum to the same value. Each sum must contain
/// divisor values that are not in the other sum, and all of the divisors must
/// be in one or the other.
fn is_zumkeller_number(number: u32) -> bool {
if number % 18 == 6 || number % 18 == 12 {
return true;
}
let div = get_divisors(number);
let divisor_sum: u32 = div.iter().sum();
if divisor_sum == 0 {
return false;
}
if divisor_sum % 2 == 1 {
return false;
}
// numbers where n is odd and the abundance is even are Zumkeller numbers
let abundance = divisor_sum as i32 - 2 * number as i32;
if number % 2 == 1 && abundance > 0 && abundance % 2 == 0 {
return true;
}
let half = divisor_sum / 2;
return div.contains(&half)
|| (div.iter().filter(|&&d| d < half).count() > 0
&& is_summable(half.try_into().unwrap(), &div));
}
fn main() {
println!("\nFirst 220 Zumkeller numbers:");
let mut counter: u32 = 0;
let mut i: u32 = 0;
while counter < 220 {
if is_zumkeller_number(i) {
print!("{:>3}", i);
counter += 1;
print!("{}", if counter % 20 == 0 { "\n" } else { "," });
}
i += 1;
}
println!("\nFirst 40 odd Zumkeller numbers:");
let mut counter: u32 = 0;
let mut i: u32 = 3;
while counter < 40 {
if is_zumkeller_number(i) {
print!("{:>5}", i);
counter += 1;
print!("{}", if counter % 20 == 0 { "\n" } else { "," });
}
i += 2;
}
}
- Output:
First 220 Zumkeller numbers: 6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96 102,104,108,112,114,120,126,132,138,140,150,156,160,168,174,176,180,186,192,198 204,208,210,216,220,222,224,228,234,240,246,252,258,260,264,270,272,276,280,282 294,300,304,306,308,312,318,320,330,336,340,342,348,350,352,354,360,364,366,368 372,378,380,384,390,396,402,408,414,416,420,426,432,438,440,444,448,456,460,462 464,468,474,476,480,486,490,492,496,498,500,504,510,516,520,522,528,532,534,540 544,546,550,552,558,560,564,570,572,580,582,588,594,600,606,608,612,616,618,620 624,630,636,640,642,644,650,654,660,666,672,678,680,684,690,696,700,702,704,708 714,720,726,728,732,736,740,744,750,756,760,762,768,770,780,786,792,798,804,810 812,816,820,822,828,832,834,836,840,852,858,860,864,868,870,876,880,888,894,896 906,910,912,918,920,924,928,930,936,940,942,945,948,952,960,966,972,978,980,984
Sidef
func is_Zumkeller(n) {
return false if n.is_prime
return false if n.is_square
var sigma = n.sigma
# n must have an even abundance
return false if (sigma.is_odd || (sigma < 2*n))
# true if n is odd and has an even abundance
return true if n.is_odd # conjecture
var divisors = n.divisors
for k in (2 .. divisors.end) {
divisors.combinations(k, {|*a|
if (2*a.sum == sigma) {
return true
}
})
}
return false
}
say "First 220 Zumkeller numbers:"
say (1..Inf -> lazy.grep(is_Zumkeller).first(220).join(' '))
say "\nFirst 40 odd Zumkeller numbers: "
say (1..Inf `by` 2 -> lazy.grep(is_Zumkeller).first(40).join(' '))
say "\nFirst 40 odd Zumkeller numbers not divisible by 5: "
say (1..Inf `by` 2 -> lazy.grep { _ % 5 != 0 }.grep(is_Zumkeller).first(40).join(' '))
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 First 40 odd Zumkeller numbers not divisible by 5: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Standard ML
exception Found of string ;
val divisors = fn n =>
let
val rec divr = fn ( c, divlist ,i) =>
if c <2*i then c::divlist
else divr (if c mod i = 0 then (c,i::divlist,i+1) else (c,divlist,i+1) )
in
divr (n,[],1)
end;
val subsetSums = fn M => fn input =>
let
val getnrs = fn (v,x) => (* out: list of numbers index where v is true + x *)
let
val rec runthr = fn (v,i,x,lst)=> if i>=M then (v,i,x,lst) else runthr (v,i+1,x,if Vector.sub(v,i) then (i+x)::lst else lst) ;
in
#4 (runthr (v,0,x,[]))
end;
val nwVec = fn (v,nrs) =>
let
val rec upd = fn (v,i,[]) => (v,i,[])
| (v,i,h::t) => upd ( case Int.compare (h,M) of
LESS => ( Vector.update (v,h,true),i+1,t)
| GREATER => (v,i+1,t)
| EQUAL => raise Found ("done "^(Int.toString h)) )
in
#1 (upd (v,0,nrs))
end;
val rec setSums = fn ([],v) => ([],v)
| (x::t,v) => setSums(t, nwVec(v, getnrs (v,x)))
in
#2 (setSums (input,Vector.tabulate (M+1,fn 0=> true|_=>false) ))
end;
val rec Zumkeller = fn n =>
let
val d = divisors n;
val s = List.foldr op+ 0 d ;
val hs = s div 2 -n ;
in
if s mod 2 = 1 orelse 0 > hs then false else
Vector.sub ( subsetSums hs (tl d) ,hs) handle Found nr => true
end;
call loop and output - interpreter
- val Zumkellerlist = fn step => fn no5 =>
let
val rec loop = fn incr => fn (i,n,v) =>
if i= (case incr of 1 => 221 | 2 => 41 | _ => 5 )
then (0,n,v)
else if n mod 5 = 0 andalso no5 then loop incr (i,n+incr,v) else
if Zumkeller n then loop incr (i+1,n+incr,(i,n)::v) else loop incr (i,n+incr,v)
in
rev (#3 ( loop step (1,3,[])))
end;
- List.app (fn x=> print (Int.toString (#2 x) ^ ", ")) (Zumkellerlist 1 false) ;
6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96, 102, 104, 108, 112, 114, 120, 126, 132,
138, 140, 150, 156, 160, 168, 174, 176, 180, 186, 192, 198, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252,
258, 260, 264, 270, 272, 276, 280, 282, 294, 300, 304, 306, 308, 312, 318, 320, 330, 336, 340, 342, 348, 350, 352, 354,
360, 364, 366, 368, 372, 378, 380, 384, 390, 396, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 456, 460, 462,
464, 468, 474, 476, 480, 486, 490, 492, 496, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552,
558, 560, 564, 570, 572, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 650, 654,
660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 740, 744, 750, 756, 760, 762,
768, 770, 780, 786, 792, 798, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 852, 858, 860, 864, 868, 870, 876,
880, 888, 894, 896, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 960, 966, 972, 978, 980, 984
- List.app (fn x=> print (Int.toString (#2 x) ^ ", ")) (Zumkellerlist 2 false) ;
945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925,
9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955,
8585, 19215, 19305
- List.app (fn x=> print (Int.toString (#2 x) ^ ", ")) (Zumkellerlist 2 true) ;
81081, 153153, 171171, 189189, 207207, 223839, 243243, 261261, 279279, 297297, 351351, 459459, 513513, 567567, 621621, 671517, 729729,
742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529,
1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377
Swift
import Foundation
extension BinaryInteger {
@inlinable
public var isZumkeller: Bool {
let divs = factors(sorted: false)
let sum = divs.reduce(0, +)
guard sum & 1 != 1 else {
return false
}
guard self & 1 != 1 else {
let abundance = sum - 2*self
return abundance > 0 && abundance & 1 == 0
}
return isPartSum(divs: divs[...], sum: sum / 2)
}
@inlinable
public func factors(sorted: Bool = true) -> [Self] {
let maxN = Self(Double(self).squareRoot())
var res = Set<Self>()
for factor in stride(from: 1, through: maxN, by: 1) where self % factor == 0 {
res.insert(factor)
res.insert(self / factor)
}
return sorted ? res.sorted() : Array(res)
}
}
@usableFromInline
func isPartSum<T: BinaryInteger>(divs: ArraySlice<T>, sum: T) -> Bool {
guard sum != 0 else {
return true
}
guard !divs.isEmpty else {
return false
}
let last = divs.last!
if last > sum {
return isPartSum(divs: divs.dropLast(), sum: sum)
}
return isPartSum(divs: divs.dropLast(), sum: sum) || isPartSum(divs: divs.dropLast(), sum: sum - last)
}
let zums = (2...).lazy.filter({ $0.isZumkeller })
let oddZums = zums.filter({ $0 & 1 == 1 })
let oddZumsWithout5 = oddZums.filter({ String($0).last! != "5" })
print("First 220 zumkeller numbers are \(Array(zums.prefix(220)))")
print("First 40 odd zumkeller numbers are \(Array(oddZums.prefix(40)))")
print("First 40 odd zumkeller numbers that don't end in a 5 are: \(Array(oddZumsWithout5.prefix(40)))")
- Output:
First 220 zumkeller numbers are: [6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96, 102, 104, 108, 112, 114, 120, 126, 132, 138, 140, 150, 156, 160, 168, 174, 176, 180, 186, 192, 198, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252, 258, 260, 264, 270, 272, 276, 280, 282, 294, 300, 304, 306, 308, 312, 318, 320, 330, 336, 340, 342, 348, 350, 352, 354, 360, 364, 366, 368, 372, 378, 380, 384, 390, 396, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 456, 460, 462, 464, 468, 474, 476, 480, 486, 490, 492, 496, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552, 558, 560, 564, 570, 572, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 650, 654, 660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 740, 744, 750, 756, 760, 762, 768, 770, 780, 786, 792, 798, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 852, 858, 860, 864, 868, 870, 876, 880, 888, 894, 896, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 960, 966, 972, 978, 980, 984] First 40 odd zumkeller numbers are: [945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305] First 40 odd zumkeller numbers that don't end in a 5 are: [81081, 153153, 171171, 189189, 207207, 223839, 243243, 261261, 279279, 297297, 351351, 459459, 513513, 567567, 621621, 671517, 729729, 742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, 1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377]
Typescript
/**
* return an array of divisors of a number(n)
* @params {number} n The number to find divisors from
* @return {number[]} divisors of n
*/
function getDivisors(n: number): number[] {
//initialize divisors array
let divisors: number[] = [1, n]
//loop through all numbers from 2 to sqrt(n)
for (let i = 2; i*i <= n; i++) {
// if i is a divisor of n
if (n % i == 0) {
// add i to divisors array
divisors.push(i);
// quotient of n/i is also a divisor of n
let j = n/i;
// if quotient is not equal to i
if (i != j) {
// add quotient to divisors array
divisors.push(j);
}
}
}
return divisors
}
/**
* return sum of an array of number
* @param {number[]} arr The array we need to sum
* @return {number} sum of arr
*/
function getSum(arr: number[]): number {
return arr.reduce((prev, curr) => prev + curr, 0)
}
/**
* check if there is a subset of divisors which sums to a specific number
* @param {number[]} divs The array of divisors
* @param {number} sum The number to check if there's a subset of divisors which sums to it
* @return {boolean} true if sum is 0, false if divisors length is 0
*/
function isPartSum(divs: number[], sum: number): boolean {
// if sum is 0, the partition is sum up to the number(sum)
if (sum == 0) return true;
//get length of divisors array
let len = divs.length;
// if divisors array is empty the partion doesnt not sum up to the number(sum)
if (len == 0) return false;
//get last element of divisors array
let last = divs[len - 1];
//create a copy of divisors array without the last element
const newDivs = [...divs];
newDivs.pop();
// if last element is greater than sum
if (last > sum) {
// recursively check if there's a subset of divisors which sums to sum using the new divisors array
return isPartSum(newDivs, sum);
}
// recursively check if there's a subset of divisors which sums to sum using the new divisors array
// or if there's a subset of divisors which sums to sum - last using the new divisors array
return isPartSum(newDivs, sum) || isPartSum(newDivs, sum - last);
}
/**
* check if a number is a Zumkeller number
* @param {number} n The number to check if it's a Zumkeller number
* @returns {boolean} true if n is a Zumkeller number, false otherwise
*/
function isZumkeller(n: number): boolean {
// get divisors of n
let divs = getDivisors(n);
// get sum of divisors of n
let sum = getSum(divs);
// if sum is odd can't be split into two partitions with equal sums
if (sum % 2 == 1) return false;
// if n is odd use 'abundant odd number' optimization
if (n % 2 == 1) {
let abundance = sum - 2 * n
return abundance > 0 && abundance%2 == 0;
}
// if n and sum are both even check if there's a partition which totals sum / 2
return isPartSum(divs, sum/2);
}
/**
* find x zumkeller numbers
* @param {number} x The number of zumkeller numbers to find
* @returns {number[]} array of x zumkeller numbers
*/
function getXZumkelers(x: number): number[] {
let zumkellers: number[] = [];
let i = 2;
let count= 0;
while (count < x) {
if (isZumkeller(i)) {
zumkellers.push(i);
count++;
}
i++;
}
return zumkellers;
}
/**
* find x Odd Zumkeller numbers
* @param {number} x The number of odd zumkeller numbers to find
* @returns {number[]} array of x odd zumkeller numbers
*/
function getXOddZumkelers(x: number): number[] {
let oddZumkellers: number[] = [];
let i = 3;
let count = 0;
while (count < x) {
if (isZumkeller(i)) {
oddZumkellers.push(i);
count++;
}
i += 2;
}
return oddZumkellers;
}
/**
* find x odd zumkeller number which are not end with 5
* @param {number} x The number of odd zumkeller numbers to find
* @returns {number[]} array of x odd zumkeller numbers
*/
function getXOddZumkellersNotEndWith5(x: number): number[] {
let oddZumkellers: number[] = [];
let i = 3;
let count = 0;
while (count < x) {
if (isZumkeller(i) && i % 10 != 5) {
oddZumkellers.push(i);
count++;
}
i += 2;
}
return oddZumkellers;
}
//get the first 220 zumkeller numbers
console.log("First 220 Zumkeller numbers: ", getXZumkelers(220));
//get the first 40 odd zumkeller numbers
console.log("First 40 odd Zumkeller numbers: ", getXOddZumkelers(40));
//get the first 40 odd zumkeller numbers which are not end with 5
console.log("First 40 odd Zumkeller numbers which are not end with 5: ", getXOddZumkellersNotEndWith5(40));
- Output:
"First 220 Zumkeller numbers: ", [6, 12, 20, 24, 28, 30, 40, 42, 48, 54, 56, 60, 66, 70, 78, 80, 84, 88, 90, 96, 102, 104, 108, 112, 114, 120, 126, 132, 138, 140, 150, 156, 160, 168, 174, 176, 180, 186, 192, 198, 204, 208, 210, 216, 220, 222, 224, 228, 234, 240, 246, 252, 258, 260, 264, 270, 272, 276, 280, 282, 294, 300, 304, 306, 308, 312, 318, 320, 330, 336, 340, 342, 348, 350, 352, 354, 360, 364, 366, 368, 372, 378, 380, 384, 390, 396, 402, 408, 414, 416, 420, 426, 432, 438, 440, 444, 448, 456, 460, 462, 464, 468, 474, 476, 480, 486, 490, 492, 496, 498, 500, 504, 510, 516, 520, 522, 528, 532, 534, 540, 544, 546, 550, 552, 558, 560, 564, 570, 572, 580, 582, 588, 594, 600, 606, 608, 612, 616, 618, 620, 624, 630, 636, 640, 642, 644, 650, 654, 660, 666, 672, 678, 680, 684, 690, 696, 700, 702, 704, 708, 714, 720, 726, 728, 732, 736, 740, 744, 750, 756, 760, 762, 768, 770, 780, 786, 792, 798, 804, 810, 812, 816, 820, 822, 828, 832, 834, 836, 840, 852, 858, 860, 864, 868, 870, 876, 880, 888, 894, 896, 906, 910, 912, 918, 920, 924, 928, 930, 936, 940, 942, 945, 948, 952, 960, 966, 972, 978, 980, 984] "First 40 odd Zumkeller numbers: ", [945, 1575, 2205, 2835, 3465, 4095, 4725, 5355, 5775, 5985, 6435, 6615, 6825, 7245, 7425, 7875, 8085, 8415, 8505, 8925, 9135, 9555, 9765, 10395, 11655, 12285, 12705, 12915, 13545, 14175, 14805, 15015, 15435, 16065, 16695, 17325, 17955, 18585, 19215, 19305] "First 40 odd Zumkeller numbers which are not end with 5: ", [81081, 153153, 171171, 189189, 207207, 223839, 243243, 261261, 279279, 297297, 351351, 459459, 513513, 567567, 621621, 671517, 729729, 742203, 783783, 793611, 812889, 837837, 891891, 908523, 960687, 999999, 1024947, 1054053, 1072071, 1073709, 1095633, 1108107, 1145529, 1162161, 1198197, 1224531, 1270269, 1307691, 1324323, 1378377]
Visual Basic .NET
Module Module1
Function GetDivisors(n As Integer) As List(Of Integer)
Dim divs As New List(Of Integer) From {
1, n
}
Dim i = 2
While i * i <= n
If n Mod i = 0 Then
Dim j = n \ i
divs.Add(i)
If i <> j Then
divs.Add(j)
End If
End If
i += 1
End While
Return divs
End Function
Function IsPartSum(divs As List(Of Integer), sum As Integer) As Boolean
If sum = 0 Then
Return True
End If
Dim le = divs.Count
If le = 0 Then
Return False
End If
Dim last = divs(le - 1)
Dim newDivs As New List(Of Integer)
For i = 1 To le - 1
newDivs.Add(divs(i - 1))
Next
If last > sum Then
Return IsPartSum(newDivs, sum)
End If
Return IsPartSum(newDivs, sum) OrElse IsPartSum(newDivs, sum - last)
End Function
Function IsZumkeller(n As Integer) As Boolean
Dim divs = GetDivisors(n)
Dim sum = divs.Sum()
REM if sum is odd can't be split into two partitions with equal sums
If sum Mod 2 = 1 Then
Return False
End If
REM if n is odd use 'abundant odd number' optimization
If n Mod 2 = 1 Then
Dim abundance = sum - 2 * n
Return abundance > 0 AndAlso abundance Mod 2 = 0
End If
REM if n and sum are both even check if there's a partition which totals sum / 2
Return IsPartSum(divs, sum \ 2)
End Function
Sub Main()
Console.WriteLine("The first 220 Zumkeller numbers are:")
Dim i = 2
Dim count = 0
While count < 220
If IsZumkeller(i) Then
Console.Write("{0,3} ", i)
count += 1
If count Mod 20 = 0 Then
Console.WriteLine()
End If
End If
i += 1
End While
Console.WriteLine()
Console.WriteLine("The first 40 odd Zumkeller numbers are:")
i = 3
count = 0
While count < 40
If IsZumkeller(i) Then
Console.Write("{0,5} ", i)
count += 1
If count Mod 10 = 0 Then
Console.WriteLine()
End If
End If
i += 2
End While
Console.WriteLine()
Console.WriteLine("The first 40 odd Zumkeller numbers which don't end in 5 are:")
i = 3
count = 0
While count < 40
If i Mod 10 <> 5 AndAlso IsZumkeller(i) Then
Console.Write("{0,7} ", i)
count += 1
If count Mod 8 = 0 Then
Console.WriteLine()
End If
End If
i += 2
End While
End Sub
End Module
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
V (Vlang)
fn get_divisors(n int) []int {
mut divs := [1, n]
for i := 2; i*i <= n; i++ {
if n%i == 0 {
j := n / i
divs << i
if i != j {
divs << j
}
}
}
return divs
}
fn sum(divs []int) int {
mut sum := 0
for div in divs {
sum += div
}
return sum
}
fn is_part_sum(d []int, sum int) bool {
mut divs := d.clone()
if sum == 0 {
return true
}
le := divs.len
if le == 0 {
return false
}
last := divs[le-1]
divs = divs[0 .. le-1]
if last > sum {
return is_part_sum(divs, sum)
}
return is_part_sum(divs, sum) || is_part_sum(divs, sum-last)
}
fn is_zumkeller(n int) bool {
divs := get_divisors(n)
s := sum(divs)
// if sum is odd can't be split into two partitions with equal sums
if s%2 == 1 {
return false
}
// if n is odd use 'abundant odd number' optimization
if n%2 == 1 {
abundance := s - 2*n
return abundance > 0 && abundance%2 == 0
}
// if n and sum are both even check if there's a partition which totals sum / 2
return is_part_sum(divs, s/2)
}
fn main() {
println("The first 220 Zumkeller numbers are:")
for i, count := 2, 0; count < 220; i++ {
if is_zumkeller(i) {
print("${i:3} ")
count++
if count%20 == 0 {
println('')
}
}
}
println("\nThe first 40 odd Zumkeller numbers are:")
for i, count := 3, 0; count < 40; i += 2 {
if is_zumkeller(i) {
print("${i:5} ")
count++
if count%10 == 0 {
println('')
}
}
}
println("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:")
for i, count := 3, 0; count < 40; i += 2 {
if (i % 10 != 5) && is_zumkeller(i) {
print("${i:7} ")
count++
if count%8 == 0 {
println('')
}
}
}
println('')
}
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
Wren
I've reversed the order of the recursive calls in the last line of the isPartSum function which, as noted in the Phix entry, seems to make little difference to Go but (as one might have expected) speeds up this Wren script enormously. The first part is now near instant but was taking several minutes previously. Overall it's now only about 5.5 times slower than Go itself which is a good result for the Wren interpreter.
import "./math" for Int, Nums
import "./fmt" for Fmt
import "io" for Stdout
var isPartSum // recursive
isPartSum = Fn.new { |divs, sum|
if (sum == 0) return true
if (divs.count == 0) return false
var last = divs[-1]
divs = divs[0...-1]
if (last > sum) return isPartSum.call(divs, sum)
return isPartSum.call(divs, sum-last) || isPartSum.call(divs, sum)
}
var isZumkeller = Fn.new { |n|
var divs = Int.divisors(n)
var sum = Nums.sum(divs)
// if sum is odd can't be split into two partitions with equal sums
if (sum % 2 == 1) return false
// if n is odd use 'abundant odd number' optimization
if (n % 2 == 1) {
var abundance = sum - 2 * n
return abundance > 0 && abundance % 2 == 0
}
// if n and sum are both even check if there's a partition which totals sum / 2
return isPartSum.call(divs, sum / 2)
}
System.print("The first 220 Zumkeller numbers are:")
var count = 0
var i = 2
while (count < 220) {
if (isZumkeller.call(i)) {
Fmt.write("$3d ", i)
Stdout.flush()
count = count + 1
if (count % 20 == 0) System.print()
}
i = i + 1
}
System.print("\nThe first 40 odd Zumkeller numbers are:")
count = 0
i = 3
while (count < 40) {
if (isZumkeller.call(i)) {
Fmt.write("$5d ", i)
Stdout.flush()
count = count + 1
if (count % 10 == 0) System.print()
}
i = i + 2
}
System.print("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:")
count = 0
i = 3
while (count < 40) {
if ((i % 10 != 5) && isZumkeller.call(i)) {
Fmt.write("$7d ", i)
Stdout.flush()
count = count + 1
if (count % 8 == 0) System.print()
}
i = i + 2
}
System.print()
- Output:
The first 220 Zumkeller numbers are: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 The first 40 odd Zumkeller numbers are: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
zkl
fcn properDivs(n){ // does not include n
// if(n==1) return(T); // we con't care about this case
( pd:=[1..(n).toFloat().sqrt()].filter('wrap(x){ n%x==0 }) )
.pump(pd,'wrap(pd){ if(pd!=1 and (y:=n/pd)!=pd ) y else Void.Skip })
}
fcn canSum(goal,divs){
if(goal==0 or divs[0]==goal) return(True);
if(divs.len()>1){
if(divs[0]>goal) return(canSum(goal,divs[1,*])); // tail recursion
else return(canSum(goal - divs[0], divs[1,*]) or canSum(goal, divs[1,*]));
}
False
}
fcn isZumkellerW(n){ // a filter for a iterator
ds,sum := properDivs(n), ds.sum(0) + n;
// if sum is odd, it can't be split into two partitions with equal sums
if(sum.isOdd) return(Void.Skip);
// if n is odd use 'abundant odd number' optimization
if(n.isOdd){
abundance:=sum - 2*n;
return( if(abundance>0 and abundance.isEven) n else Void.Skip);
}
canSum(sum/2,ds) and n or Void.Skip // sum is even
}
println("First 220 Zumkeller numbers:");
zw:=[2..].tweak(isZumkellerW);
do(11){ zw.walk(20).pump(String,"%4d ".fmt).println() }
println("\nFirst 40 odd Zumkeller numbers:");
zw:=[3..*, 2].tweak(isZumkellerW);
do(4){ zw.walk(10).pump(String,"%5d ".fmt).println() }
println("\nThe first 40 odd Zumkeller numbers which don't end in 5 are:");
zw:=[3..*, 2].tweak(fcn(n){ if(n%5) isZumkellerW(n) else Void.Skip });
do(5){ zw.walk(8).pump(String,"%7d ".fmt).println() }
- Output:
First 220 Zumkeller numbers: 6 12 20 24 28 30 40 42 48 54 56 60 66 70 78 80 84 88 90 96 102 104 108 112 114 120 126 132 138 140 150 156 160 168 174 176 180 186 192 198 204 208 210 216 220 222 224 228 234 240 246 252 258 260 264 270 272 276 280 282 294 300 304 306 308 312 318 320 330 336 340 342 348 350 352 354 360 364 366 368 372 378 380 384 390 396 402 408 414 416 420 426 432 438 440 444 448 456 460 462 464 468 474 476 480 486 490 492 496 498 500 504 510 516 520 522 528 532 534 540 544 546 550 552 558 560 564 570 572 580 582 588 594 600 606 608 612 616 618 620 624 630 636 640 642 644 650 654 660 666 672 678 680 684 690 696 700 702 704 708 714 720 726 728 732 736 740 744 750 756 760 762 768 770 780 786 792 798 804 810 812 816 820 822 828 832 834 836 840 852 858 860 864 868 870 876 880 888 894 896 906 910 912 918 920 924 928 930 936 940 942 945 948 952 960 966 972 978 980 984 First 40 odd Zumkeller numbers: 945 1575 2205 2835 3465 4095 4725 5355 5775 5985 6435 6615 6825 7245 7425 7875 8085 8415 8505 8925 9135 9555 9765 10395 11655 12285 12705 12915 13545 14175 14805 15015 15435 16065 16695 17325 17955 18585 19215 19305 The first 40 odd Zumkeller numbers which don't end in 5 are: 81081 153153 171171 189189 207207 223839 243243 261261 279279 297297 351351 459459 513513 567567 621621 671517 729729 742203 783783 793611 812889 837837 891891 908523 960687 999999 1024947 1054053 1072071 1073709 1095633 1108107 1145529 1162161 1198197 1224531 1270269 1307691 1324323 1378377
- Programming Tasks
- Prime Numbers
- 11l
- AArch64 Assembly
- AppleScript
- ARM Assembly
- C sharp
- C++
- D
- EasyLang
- F Sharp
- Factor
- Go
- Haskell
- J
- Java
- Jq
- Julia
- Kotlin
- Lobster
- Mathematica
- Wolfram Language
- Nim
- PARI/GP
- Pascal
- Perl
- Ntheory
- Phix
- PicoLisp
- Python
- Racket
- Raku
- REXX
- Ring
- Ruby
- Rust
- Sidef
- Standard ML
- Swift
- Typescript
- Visual Basic .NET
- V (Vlang)
- Wren
- Wren-math
- Wren-fmt
- Zkl