Zumkeller numbers

From Rosetta Code
Revision as of 12:32, 11 June 2021 by rosettacode>Gerard Schildberger (added a category.)
Task
Zumkeller numbers
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


Related Tasks

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits

<lang 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" </lang> Template:Output:

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

This takes about 0.38 seconds to execute the two main searches — then a further 109 for the stretch goal!

<lang applescript>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

on canSumTo(lst, target)

   script o
       property l : lst
       
       on cst(target, i)
           repeat
               set n to item i of my l
               if (n = target) then return true
               if (i = 1) then return false
               set i to i - 1
               if ((n < target) and (cst(target - n, i))) then return true
           end repeat
       end cs
   end script
   
   return o's cst(target, count o's l)

end canSumTo

on isZumkeller(n)

   script o
       property divisors : properDivisors(n)
   end script
   
   set sum to n
   repeat with thisDivisor in o's divisors
       set sum to sum + thisDivisor
   end repeat
   set halfSum to sum / 2
   
   return ((halfSum ≥ n) and (halfSum as integer = halfSum) and (canSumTo(o's divisors, halfSum)))

end isZumkeller

-- Task code: on zumkellerNumbers(target, n, interval, filter)

   -- Params: how many required, first number to test, interval between numbers tested,
   --        script object imposing any further restrictions on the numbers.
   script o
       property zumkellers : {}
   end script
   
   set counter to 0
   repeat until (counter = target)
       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 format(resultList, heading, resultsPerLine, separator)

   script o
       property input : resultList
       property output : {heading}
   end script
   
   set astid to AppleScript's text item delimiters
   set AppleScript's text item delimiters to separator
   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 (items i thru j of o's input) as text
   end repeat
   set AppleScript's text item delimiters to linefeed
   set output to o's output as text
   set AppleScript's text item delimiters to astid
   return output

end format

on doTask()

   set output to {}
   script default
       on OK(n)
           return true
       end OK
   end script
   set header to "1st 220 Zumkeller numbers:"
   set end of output to format(zumkellerNumbers(220, 1, 1, default), header, 20, "  ")
   set header to "1st 40 odd Zumkeller numbers:"
   set end of output to format(zumkellerNumbers(40, 1, 2, default), header, 10, "  ")
   set header to "1st 40 odd Zumkeller numbers not ending with 5:"
   script notDivisibleBy5
       on OK(n)
           return (n mod 5 > 0)
       end OK
   end script
   set end of output to format(zumkellerNumbers(40, 1, 2, notDivisibleBy5), header, 10, "  ")
   set astid to AppleScript's text item delimiters
   set AppleScript's text item delimiters to linefeed & linefeed
   set output to output as text
   set AppleScript's text item delimiters to astid
   return output

end doTask

doTask()</lang>

Output:

<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 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"</lang>

ARM Assembly

Works with: as version Raspberry Pi

<lang 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" </lang>

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#

Translation of: Go

<lang csharp>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();
                   }
               }
           }
       }
   }

}</lang>

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++

<lang cpp>#include <iostream>

  1. include <cmath>
  2. include <vector>
  3. include <algorithm>
  4. include <iomanip>
  5. 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;

}</lang>

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

Translation of: C#

<lang 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;
           }
       }
   }

}</lang>

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

F#

This task uses [1] <lang fsharp> // 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" </lang>

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

Works with: Factor version 0.99 2019-10-06

<lang 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</lang>

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

<lang 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()

}</lang>

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

Translation of: Python

<lang 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 <>)</lang>

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

Java

<lang 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;
   }

} </lang>

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

Julia

<lang 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)

</lang>

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

Translation of: Java

<lang scala>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
   }

}</lang>

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

<lang 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) </lang>

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

<lang Mathematica>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];
   t1 + 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</lang>

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

Translation of: Go

<lang 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</lang>
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

Pascal

modified practical numbers and Factors_of_an_integer#using_Prime_decomposition
prime decomposition included to get it run on TIO.RUN
Now using the trick, that one partition sum must include n and improved recursive search. <lang pascal>program zumkeller; //https://oeis.org/A083206/a083206.txt {$IFDEF FPC}

 {$MODE DELPHI}  {$OPTIMIZATION ON,ALL}  {$COPERATORS ON}

{$ELSE}

 {$APPTYPE CONSOLE}

{$ENDIF} uses

 sysutils

{$IFDEF WINDOWS},Windows{$ENDIF}

 ;

//###################################################################### //prime decomposition type

 tItem     = Uint32;
 tDivisors = array [0..1920] of tItem;
 tpDivisor = pUint32;
 tPot = record
          potSoD : Uint64;
          potPrim,
          potMax :Uint32;
        end;
 tprimeFac = record
                pfPrims : array[0..15] of tPot;
                pfSumOfDivs :Uint64;
                pfCnt,
                pfDivCnt,
                pfNum,pfdummy    : Uint32;
              end;


type

 tSmallPrimes = array[0..6541] of Word;

var

 SmallPrimes: tSmallPrimes;
 isSmallPrimesInited : boolean = false;

procedure InitSmallPrimes; var

 pr,testPr,j,maxprimidx: Uint32;
 isPrime : boolean;

Begin

 maxprimidx := 0;
 SmallPrimes[0] := 2;
 pr := 3;
 repeat
   isprime := true;
   j := 0;
   repeat
     testPr := SmallPrimes[j];
     IF sqr(testPr) > pr then
       break;
     If pr mod testPr = 0 then
     Begin
       isprime := false;
       break;
     end;
     inc(j);
   until false;
   if isprime then
   Begin
     inc(maxprimidx);
     SmallPrimes[maxprimidx]:= pr;
   end;
   inc(pr,2);
 until pr > 1 shl 16 -1;
 isSmallPrimesInited:= true;

end;

function DivCount(const pD:tprimeFac):NativeUInt;inline; begin

 result := pD.pfDivCnt;

end;

function SumOfDiv(const pD:tprimeFac):Uint64;inline; begin

 result := pD.pfSumOfDivs;

end;

procedure PrimeDecomposition(n:Uint32;var res:tprimeFac); Label

 Finished;

var

 DivSum,fac:Uint64;
 i,pr,cnt,DivCnt,quot{to minimize divisions} : Uint32;

Begin

 if Not(isSmallPrimesInited) then
   InitSmallPrimes;
 //already done
 if res.pfNum = n then
   EXIT;
 res.pfNum := n;
 cnt := 0;
 DivCnt := 1;
 DivSum := 1;
 i := 0;
 if n <= 1 then
 Begin
   with res.pfPrims[0] do
   Begin
     potPrim := n;
     potMax  := 1;
   end;
   cnt := 1;
 end
 else
 Begin
   pr := 2;
   IF 2*2>n then
     GOTO Finished;
   quot := n div 2;
   IF 2*quot = n then
   Begin
     with res do
       with pfPrims[Cnt] do
       Begin
         potPrim := 2;
         potMax := 0;
         fac := 2;
         repeat
           n := quot;
           quot := quot div 2;
           inc(potMax);
           fac *= 2;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1)DIV (2-1);
         potSoD := DivSum;
       end;
     inc(Cnt);
   end;
   pr := 3;
   IF 3*3>n then
     GOTO Finished;
   quot := n div 3;
   IF 3*quot = n then
   begin
     with res do
     Begin
       with pfPrims[Cnt] do
       Begin
         potPrim := 3;
         potMax := 0;
         fac := 3;
         repeat
           n := quot;
           quot := quot div 3;
           inc(potMax);
           fac *= 3;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1) DIV (3-1);
         potSoD := DivSum;
       end;
     end;
     inc(Cnt);
   end;
   pr := 5;
   IF 5*5>n then
     GOTO Finished;
   quot := n div 5;
   IF 5*quot = n then
   begin
     with res do
     Begin
       with pfPrims[Cnt] do
       Begin
         potPrim := 5;
         potMax := 0;
         fac := 5;
         repeat
           n := quot;
           quot := quot div 5;
           inc(potMax);
           fac *= 5;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1) DIV (5-1);
         potSoD := DivSum;
       end;
     end;
     inc(Cnt);
   end;
   pr := 7;
   IF 7*7>n then
     GOTO Finished;
   quot := n div 7;
   IF 7*quot = n then
   begin
     with res do
     Begin
       with pfPrims[Cnt] do
       Begin
         potPrim := 7;
         potMax := 0;
         fac := 7;
         repeat
           n := quot;
           quot := quot div 7;
           inc(potMax);
           fac *= 7;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1) DIV (7-1);
         potSoD := DivSum;
       end;
     end;
     inc(Cnt);
   end;
   pr := 11;
   IF 11*11>n then
     GOTO Finished;
   quot := n div 11;
   IF 11*quot = n then
   begin
     with res do
     Begin
       with pfPrims[Cnt] do
       Begin
         potPrim := 11;
         potMax := 0;
         fac := 11;
         repeat
           n := quot;
           quot := quot div 11;
           inc(potMax);
           fac *= 11;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1) DIV (11-1);
         potSoD := DivSum;
       end;
     end;
     inc(Cnt);
   end;
   pr := 13;
   IF 13*13>n then
     GOTO Finished;
   quot := n div 13;
   IF 13*quot = n then
   begin
     with res do
     Begin
       with pfPrims[Cnt] do
       Begin
         potPrim := 13;
         potMax := 0;
         fac := 13;
         repeat
           n := quot;
           quot := quot div 13;
           inc(potMax);
           fac *= 13;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1) DIV (13-1);
         potSoD := DivSum;
       end;
     end;
     inc(Cnt);
   end;
 i := 6;
 repeat
   pr := SmallPrimes[i];
   IF pr*pr>n then
     Break;
   quot := n div pr;
   IF pr*quot = n then
     with res do
     Begin
       with pfPrims[Cnt] do
       Begin
         potPrim := pr;
         potMax := 0;
         fac := pr;
         repeat
           n := quot;
           quot := quot div pr;
           inc(potMax);
           fac *= pr;
         until pr*quot <> n;
         DivCnt *= (potMax+1);
         DivSum *= (fac-1)DIV(pr-1);
         potSoD := DivSum;
       end;
       inc(Cnt);
     end;
    inc(i);
 until false;

Finished:

 //a big prime left over?
 IF n > 1 then
   with res do
   Begin
     with pfPrims[Cnt] do
     Begin
       potPrim := n;
       potMax := 1;
     inc(Cnt);
     DivCnt *= 2;
     DivSum *= n+1;
     potSoD := DivSum;
     end;
   end;
 end;
 res.pfCnt:= cnt;
 res.pfDivCnt := DivCnt;
 res.pfSumOfDivs := DivSum;

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:tDivisors); var

 pDivs : tpDivisor;
 i,len,j,l,p,pPot,k: NativeInt;

Begin

 i := DivCount(pD);
 pDivs := @Divs[0];
 pDivs[0] := 1;
 len := 1;
 l   := 1;
 For i := 0 to pD.pfCnt-1 do
   with pD.pfPrims[i] do
   Begin
     //Multiply every divisor before with the new primefactors
     //and append them to the list
     k := potMax-1;
     p := potPrim;
     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;
 //Sort. Insertsort much faster than QuickSort in this special case
 InsertSort(pDivs,0,len-1);

end;

function OutPots(const pD:tprimeFac):Ansistring; var

 s: String;
 i: NativeInt;

Begin

 str(pD.pfNum:10,s);
 result := s+' :';
 str(DivCount(pD):5,s);
 result += s+' : ';
 For i := 0 to pD.pfCnt-1 do
   with pD.pfPrims[i] do
   Begin
     if i>0 then
       result += '*';
     str(potPrim,s);
     result += s;
     if potMax >1 then
     Begin
       str(potMax,s);
       result += '^'+s;
     end;
   end;

// str(SumOfDiv(pD):12,s);result := ' '+s+' ';

 For i := 0 to pD.pfCnt-1 do
   with pD.pfPrims[i] do
   Begin
     str(potSod,s);
     result += ';'+s;
   end;

end; //prime decomposition //######################################################################

type

 tSol = array of Uint32;
 tpHasSum =pByte;

var

 //no more than 1920 divisors von UInt32 ( HCN ) 
 prechecked_Idx : array[0..1920] of Uint32;
 SumOfDivs : array[0..1920] of Uint64;
 sol : tSol;
 Divs: tDivisors;
 pDiv :tpDivisor;
 T0: Int64;
 depth : NativeInt;
 count,rek_count: NativeInt;
 finished :Boolean;

procedure Out_One_Sol(const pd:tprimefac); //shows prime decomposition and the used divisors to get the sum ( n is excluded ) var

 i : NativeInt;

Begin

 i := DivCount(pD);
 writeln(OutPots(pD));
 write(SumOfDiv(pD)shr 1 - pd.pfNum:10,' = ');
 i:= 0;
 while prechecked_idx[i] > 0 do
 Begin
   write(prechecked_idx[i],'+');
   inc(i);
 end;
 writeln(i:4,rek_count:12);

end;

procedure OutSol(const sol:tsol;colWidth,ColCount:NativeInt); var

 i,col: NativeInt;

Begin

 col := ColCount;
 For i := 0 to High(sol) do
 begin
   write(' ',Sol[i]:colWidth-1);
   dec(col);
   if col = 0 then
   Begin
     writeln;
     col := ColCount;
   end;
 end;
 writeln;

end;

procedure Check_rek(SoD : Int64;i: NativeInt); var

 sum : Int64;

begin

 inc(rek_Count);
 WHILE (i>0) AND (pDiv[i]>SoD) do
   dec(i);
 inc(depth);
 while i >= 0 do
 Begin
   prechecked_idx[depth] := pDiv[i];
   sum := SoD-pDiv[i];
   if sum = 0 then
   begin
     finished := true;
     prechecked_idx[depth+1] := 0;
     EXIT;
   end;
   dec(i);
   if  (i>=0) AND (sum<=SumOfDivs[i]) then
     Check_rek(sum,i);
   if finished then
     EXIT;
   prechecked_idx[depth] := 0;
 end;
 dec(depth);

end;

function GetZumKeller(n: Uint32;var primeDecomp:tPrimefac): boolean; var

 SoD,sum : Int64;
 Div_cnt,i: NativeInt;

begin

 rek_count := 0;
 result   := false;
 PrimeDecomposition(n,primeDecomp);
 SoD := SumOfDiv(primeDecomp);
 //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);
 //idx [0..DivCount(primeDecomp)-1];
 Div_cnt := DivCount(primeDecomp)-1;
 if Not(odd(n)) then
   if ((n mod 18) in [6,12]) then
     EXIT(true);
 //Now one needs to get the divisors
 GetDivs(primeDecomp,Divs);
 
 //create a table of remaining sum 
 finished := true;
 sum := 1;
 SumOfDivs[0] := sum;
 For i := 1 to Div_Cnt-1 do
 Begin
   If (sum+1<Divs[i]) AND (sum<SoD) then
     finished := false;
   sum += Divs[i];
   SumOfDivs[i] := sum;
   If sum >SoD then
     break;
 end;
 //practical < SoD
 if finished then
   Exit(true);
 finished := false;
 IF Div_cnt <= 1920 then
 Begin
   prechecked_idx[0]:= 0;
   depth := -1;
   pDiv := @Divs[0];
   Check_rek(SoD,Div_cnt-1);
   exit(finished);
 end;

end;

procedure CheckSpecial(n:Uint32;var primeDecomp:tPrimeFac); var

 isZK : boolean;

Begin

 isZK:=GetZumKeller(n,primeDecomp);
 writeln(n:10,' SumOfDivs ',SumOfDiv(primeDecomp):11,' CountOfDivs ',DivCount(primeDecomp),' isZk ',isZK);
 writeln('rec ',rek_count:8,OutPots(primeDecomp));

end;

var

 primeDecomp : tPrimeFac;
 n: NativeInt;

BEGIN

 T0 := GetTickCount64;
 writeln('Count of zumkeller numbers up to 10,000,000');
 n := 1;
 count :=0;
 repeat
   if GetZumKeller(n,primeDecomp) then
   begin

// if count AND 16383 = 16383 then write(n,#13);

     inc(count);
   end;
   inc(n);
 until n > 10*1000*1000;
 writeln(count:10,n-1:10);
 T0 := GetTickCount64-T0;
 writeln('runtime ',T0/1000:0:3,' s');
 writeln(#10,'First 220 zumkeller');
 T0 := GetTickCount64;
 n := 1;
 count :=0;
 setlength(sol,220);
 repeat
   if GetZumKeller(n,primeDecomp) then
   begin
     sol[count] := n;
     inc(count);
   end;
   inc(n,1);
 until count >= length(sol);
 OutSol(sol,4,20);
 T0 := GetTickCount64-T0;
 writeln('runtime ',T0/1000:0:3,' s');
 T0 := GetTickCount64;
 n := -1;
 count :=0;
 setlength(sol,40);
 writeln(#10,'First 40 odd zumkeller numbers');
 repeat
   inc(n,2);
   if GetZumKeller(n,primeDecomp) then
   begin
     sol[count] := n;
     inc(count);
   end;
 until count>=length(sol);
 OutSol(sol,10,8);
 T0 := GetTickCount64-T0;
 writeln('runtime ',T0/1000:0:3,' s');
 T0 := GetTickCount64;
 n := 1;
 count :=0;
 setlength(sol,40);
 writeln(#10,'First 40 odd zumkeller numbers not multiple of 5');
 repeat
   if GetZumKeller(n,primeDecomp) then
   begin
     sol[count] := n;
     inc(count);
   end;
   inc(n,2);
   if n mod 5 = 0 then
     inc(n,2);
 until count>=length(sol);
 OutSol(sol,10,8);
 T0 := GetTickCount64-T0;
 writeln('runtime ',T0/1000:0:3,' s');
 T0 := GetTickCount64;
 CheckSpecial(3492,primeDecomp);
 CheckSpecial(14184,primeDecomp);
 CheckSpecial(58896,primeDecomp);
 CheckSpecial(236448,primeDecomp);
 CheckSpecial(954432,primeDecomp);
 CheckSpecial(2549700,primeDecomp);
 CheckSpecial(10884600,primeDecomp);
 T0 := GetTickCount64-T0;
 writeln('runtime ',T0/1000:0:3,' s');
 setlength(sol,0);
 {$IFNDEF UNIX}  readln; {$ENDIF}

END.</lang>

Output:
TIO.RUN 

Count of zumkeller numbers up to 10,000,000
   2287889  10000000
runtime 6.494 s //1,000,000 takes 0.257 s

First 220 zumkeller
   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

runtime 0.000 s

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

runtime 0.001 s

First 40 odd zumkeller numbers not multiple of 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

runtime 0.175 s
      3492 SumOfDivs        8918 CountOfDivs 18 isZk FALSE
rec        7      3492 :   18 : 2^2*3^2*97;7;91;8918
     14184 SumOfDivs       38610 CountOfDivs 24 isZk FALSE
rec       19     14184 :   24 : 2^3*3^2*197;15;195;38610
     58896 SumOfDivs      165230 CountOfDivs 30 isZk FALSE
rec       38     58896 :   30 : 2^4*3^2*409;31;403;165230
    236448 SumOfDivs      673218 CountOfDivs 36 isZk FALSE
rec      130    236448 :   36 : 2^5*3^2*821;63;819;673218
    954432 SumOfDivs     2737358 CountOfDivs 42 isZk FALSE
rec      513    954432 :   42 : 2^6*3^2*1657;127;1651;2737358
   2549700 SumOfDivs     7994714 CountOfDivs 54 isZk FALSE
rec     2211   2549700 :   54 : 2^2*3^2*5^2*2833;7;91;2821;7994714
  10884600 SumOfDivs    36560160 CountOfDivs 72 isZk FALSE
rec   853112  10884600 :   72 : 2^3*3^2*5^2*6047;15;195;6045;36560160
runtime 0.132 s

Real time: 7.132 s CPU share: 99.18 %

NEW: Much faster: tested count of odd zumkeller numbers ti 1,000,000,000

count of odd zumkeller numbers up to 1,000,000,000
    n            count     count/      time
                         prechecked
    10000000       20637  96.860 %     2.839 s
    20000000       41463  96.698 %     7.519 s
    30000000       62002  96.637 %    13.391 s
    40000000       82513  96.474 %    20.381 s
    50000000      103001  96.351 %    28.329 s
    60000000      123482  96.283 %    37.077 s
    70000000      143933  96.232 %    46.573 s
    80000000      164412  96.202 %    56.877 s
    90000000      184816  96.165 %    67.944 s
   100000000      205283  96.152 %    79.329 s
   150000000      307454  95.956 %   148.857 s
   200000000      409569  95.835 %   239.997 s
   250000000      511807  95.796 %   344.792 s
   300000000      613721  95.792 %   478.399 s
   400000000      817456  95.743 %   840.497 s
   500000000     1021438  95.720 %  1291.123 s
   600000000     1225716  95.708 %  1820.230 s
   700000000     1430227  95.683 %  2461.841 s
   800000000     1634217  95.625 %  3263.611 s
   900000000     1838186  95.569 %  4161.572 s
  1000000000     2042196  95.526 %  5134.790 s
   2042196 999999999 pre checked 1950822

Tested odd zumkeller numbers up to 500,000,000 aka 5*10^8 , which takes 14h
All 205283 odd abundant numbers less than 10^8 that have even abundance are Zumkeller numbers. - T. D. Noe, Nov 14 2010
And yes there was no odd zumkeller with odd abundance->last prime factor must have a even power >0 2,4,6...

 1 h5m33 ->138978315 runtime 3933.063 s
+12 h   ->482567085
+13 h   ->501864363 stopped
 count;number;SumOfDivs;CountofDivs;number : prime decomposition        
  10159    4999995;    12257280;  128 ; 4999995 : 3^3*5*7*11*13*37
  10160    5000625;    10396672;   60 ; 5000625 : 3^2*5^4*7*127

  20637    9999825;    20570112;   96 ; 9999825 : 3*5^2*11*17*23*31
  20638   10000305;    20217600;   48 ; 10000305 : 3^2*5*7*53*599

  41463   19999875;    40135680;   64 ; 19999875 : 3*5^3*7*19*401
  41464   20000925;    45372096;  120 ; 20000925 : 3^4*5^2*7*17*83

  62002   29999475;    66852864;  144 ; 29999475 : 3^2*5^2*11*17*23*31
  62003   30000915;    62208000;   64 ; 30000915 : 3^3*5*7*53*599

  82513   39999645;    82697472;   48 ; 39999645 : 3^2*5*7*23*5521
  82514   40000275;    82985760;   72 ; 40000275 : 3^2*5^2*7*109*233

 103001   49999635;   104884416;   48 ; 49999635 : 3^2*5*7*17*9337
 103002   50000895;   102735360;   48 ; 50000895 : 3^5*5*7*5879

 205283   99999375;   200935680;   80 ; 99999375 : 3*5^4*7*19*401 //205283 odd abundant numbers less than 10^8
 205284  100000845;   217728000;  128 ; 100000845 : 3^3*5*7*29*41*89

 307454  149999535;   307841040;   72 ; 149999535 : 3^2*5*7^2*59*1153
 307455  150000165;   306748416;   48 ; 150000165 : 3^2*5*7*31*15361

 409569  199999305;   400443264;   48 ; 199999305 : 3^2*5*11*17*23767
 409570  200000115;   403269984;   36 ; 200000115 : 3^2*5*7^2*90703

 511807  249999435;   521314560;   48 ; 249999435 : 3^2*5*7*19*41771
 511808  250000065;   506782848;   48 ; 250000065 : 3^2*5*7*43*18457

 613721  299998755;   609523200;   32 ; 299998755 : 3^3*5*7*317459
 613722  300000645;   611696640;   64 ; 300000645 : 3^3*5*7*523*607

 715573  349998705;   742072320;   64 ; 349998705 : 3^3*5*7*23*16103
 715574  350000595;   717044064;   40 ; 350000595 : 3^4*5*7*123457

 817456  399998865;   808206336;   64 ; 399998865 : 3*5*7*17*23*9743
 817457  400000293;   803312640;   96 ; 400000293 : 3^2*7*11*17*19*1787

 919451  449999235;   922184640;   48 ; 449999235 : 3^2*5*7*29*49261
 919452  450000495;   943841280;   64 ; 450000495 : 3^3*5*7*31*15361

1021438  499999185;  1052101440;   72 ; 499999185 : 3^2*5*7^2*23*9859
1021439  500000445;  1027178880;   48 ; 500000445 : 3^5*5*7*58789

ODD Zumkeller Index;CoD Count of Divisors;Average CoD;Zumkeller number
         1;  16; 16.0000;945 : 3^3*5*7
         2;  18; 18.0000;1575 : 3^2*5^2*7
         4;  20; 19.0000;2835 : 3^4*5*7
         5;  24; 24.0000;3465 : 3^2*5*7*11
        24;  32; 24.4211;10395 : 3^3*5*7*11
        36;  36; 27.5000;17325 : 3^2*5^2*7*11
        69;  40; 30.4242;31185 : 3^4*5*7*11
       101;  48; 33.3125;45045 : 3^2*5*7*11*13
       246;  54; 37.7931;121275 : 3^2*5^2*7^2*11
       272;  64; 41.1538;135135 : 3^3*5*7*11*13
       439;  72; 43.2335;225225 : 3^2*5^2*7*11*13
       814;  80; 45.8027;405405 : 3^4*5*7*11*13
      1366;  96; 49.0688;675675 : 3^3*5^2*7*11*13
      3126; 108; 53.1364;1576575 : 3^2*5^2*7^2*11*13
      4025; 120; 55.8843;2027025 : 3^4*5^2*7*11*13
      4573; 128; 56.6752;2297295 : 3^3*5*7*11*13*17
      7715; 144; 58.4978;3828825 : 3^2*5^2*7*11*13*17
     14116; 160; 61.1239;6891885 : 3^4*5*7*11*13*17
     23733; 192; 63.7696;11486475 : 3^3*5^2*7*11*13*17
     55414; 216; 67.8331;26801775 : 3^2*5^2*7^2*11*13*17
     71154; 240; 70.7454;34459425 : 3^4*5^2*7*11*13*17
     89984; 256; 72.0990;43648605 : 3^3*5*7*11*13*17*19
    149543; 288; 74.2782;72747675 : 3^2*5^2*7*11*13*17*19
    268601; 320; 77.3901;130945815 : 3^4*5*7*11*13*17*19
    446838; 384; 80.4003;218243025 : 3^3*5^2*7*11*13*17*19
last 501864363
   1025232 84.3602;
   1025232 80.7680;501864363 : 3^3*7*11*13*31*599
CntOfDivs|Count | last occurence
  16       1       945
  18       2      2205
  20       1      2835
  24      37     32445
  28       1     25515
  30       5    108045
  32   44011 501862095
  36   47777 501859575
  40   16114 501848865
  42       6   5294205
  44       1   2066715
  48  197324 501856425
  50       4    972405
  52       1  18600435
  54    2795 499226175
  56    2254 501650415
  60   11478 501809175
  64  154291 501863985
  66       4  19190925
  70       8  47647845
  72  102440 501846975
  78       4 172718325
  80   34227 501843195
  84    1892 501788925
  88      71 498078315
  90    1987 501185475
  96  211623 501863175
  98       4 428830605
 100     670 500833125
 104       8 496897335
 108   13834 501858225
 110       3 479773125
 112    4445 501803505
 120   20477 501833475
 126     310 501701445
 128   67263 501864363
 132      32 485678025
 140     138 500731875
 144   48901 501862725
 150     136 500788575
 160   11220 501808125
 162     454 501511725
 168    1299 501570225
 176       4 456744015
 180    1599 501780825
 192   19903 501838155
 200     173 501744375
 210       6 481340475
 216    2097 501752475
 224     274 501854535
 240    1368 501860205
 252      42 499200975
 256    1163 501756255
 270      21 495685575
 280       1 456080625
 288     871 501666165
 300       2 463876875
 320      92 499926735
 324       9 471395925
 336       6 485269785
 360      13 500675175
 384      32 498513015

Perl

Library: ntheory

<lang 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);</lang>

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

Translation of: Go
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 remainder(t,2)=1 then return false end if
    -- if n is odd use 'abundant odd number' optimization
    if remainder(n,2)=1 then
        integer abundance := t - 2*n
        return abundance>0 and remainder(abundance,2)=0
    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 "},
                  {40,2,0,10,"%5d "},
                  {40,2,5,8,"%7d "}}
integer lim, step, rem, cr; string fmt
for t=1 to length(tests) do
    {lim, step, rem, cr, fmt} = tests[t]
    string odd = iff(step=1?"":"odd "),
           wch = iff(rem=0?"":"which don't end in 5 ")
    printf(1,"The first %d %sZumkeller numbers %sare:\n",{lim,odd,wch})
    integer i = step+1, count = 0
    while count<lim do
        if (rem=0 or remainder(i,10)!=rem)
        and isZumkeller(i) then
            printf(1,fmt,i)
            count += 1
            if remainder(count,cr)=0 then puts(1,"\n") end if
        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

<lang 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)

  1. 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) ) ) )</lang>
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. <lang python>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)

</lang>

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:

<lang python>Zumkeller numbers

from itertools import (

   accumulate, chain, count, groupby, islice, product

) from functools import reduce from math import floor, sqrt import operator


  1. ---------------------- ZUMKELLER -----------------------
  1. 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


  1. 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


  1. ------------------------- TEST -------------------------
  2. 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))
       )
   ))


  1. ---------------------- TABULATION ----------------------
  1. 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


  1. ----------------------- GENERIC ------------------------
  1. 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


  1. 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]


  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)


  1. even :: Int -> Bool

def even(x):

   True if x is an integer
      multiple of two.
   
   return 0 == x % 2


  1. ge :: Eq a => a -> a -> Bool

def ge(a):

   def go(b):
       return operator.ge(a, b)
   return go


  1. 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)


  1. take :: Int -> [a] -> [a]
  2. 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


  1. 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


  1. MAIN ---

if __name__ == '__main__':

   main()</lang>
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

Translation of: Zkl

<lang 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)))))</lang>
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)

Works with: Rakudo version 2019.07.1

<lang perl6>use ntheory:from<Perl5> <factor is_prime>;

sub zumkeller ($range) {

   $range.grep: -> $maybe {
       next if $maybe < 3;
       next if $maybe.&is_prime;
       my @divisors = $maybe.&factor.combinations».reduce( &[*] ).unique.reverse;
       next unless [&&] +@divisors > 2, +@divisors %% 2, (my $sum = sum @divisors) %% 2, ($sum /= 2) >= $maybe;
       my $zumkeller = False;
       if $maybe % 2 {
           $zumkeller = True
       } else {
           TEST: loop (my $c = 1; $c < @divisors / 2; ++$c) {
               @divisors.combinations($c).map: -> $d {
                   next if (sum $d) != $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";
  1. 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";</lang>
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. <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*/ 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, "═")

  1. = 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, "═")

  1. = 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, '═')

  1. = 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*/</lang>
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

<lang 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

</lang> 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

<lang 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) </lang>

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

<lang 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;
   }

} </lang>

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

<lang ruby>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(' '))</lang>

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

<lang 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; </lang> call loop and output - interpreter <lang Standard ML> - 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 </lang>

Swift

Translation of: Go

<lang 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)))")</lang>

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]

Visual Basic .NET

Translation of: C#

<lang vbnet>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</lang>

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

Translation of: Go
Library: Wren-math
Library: 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. <lang ecmascript>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()</lang>

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

Translation of: Julia
Translation of: Go

<lang 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

}</lang> <lang zkl>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() }</lang>

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 

Link title