Task: Zumkeller numbers



C#: using System;
using System.Collections.Generic;
using System.Linq;

namespace ZumkellerNumbers {
    class Program {
        static List<int> GetDivisors(int n) {
            List<int> divs = new List<int> {
                1, n
            };
            for (int i = 2; i * i <= n; i++) {
                if (n % i == 0) {
                    int j = n / i;
                    divs.Add(i);
                    if (i != j) {
                        divs.Add(j);
                    }
                }
            }
            return divs;
        }

        static bool IsPartSum(List<int> divs, int sum) {
            if (sum == 0) {
                return true;
            }
            var le = divs.Count;
            if (le == 0) {
                return false;
            }
            var last = divs[le - 1];
            List<int> newDivs = new List<int>();
            for (int i = 0; i < le - 1; i++) {
                newDivs.Add(divs[i]);
            }
            if (last > sum) {
                return IsPartSum(newDivs, sum);
            }
            return IsPartSum(newDivs, sum) || IsPartSum(newDivs, sum - last);
        }

        static bool IsZumkeller(int n) {
            var divs = GetDivisors(n);
            var sum = divs.Sum();
            
            if (sum % 2 == 1) {
                return false;
            }
            
            if (n % 2 == 1) {
                var abundance = sum - 2 * n;
                return abundance > 0 && abundance % 2 == 0;
            }
            
            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();
                    }
                }
            }
        }
    }
}



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) {
        
        if ( n % 18 == 6 || n % 18 == 12 ) {
            return true;
        }
        
        List<Integer> divisors = getDivisors(n);        
        int divisorSum = divisors.stream().mapToInt(i -> i.intValue()).sum();
        
        
        if ( divisorSum % 2 == 1 ) {
            return false;
        }
        
        
        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;
        
        
        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;
    }

}