Task: Practical numbers





Java: import java.util.*;

public class PracticalNumbers {
    public static void main(String[] args) {
        final int from = 1;
        final int to = 333;
        List<Integer> practical = new ArrayList<>();
        for (int i = from; i <= to; ++i) {
            if (isPractical(i))
                practical.add(i);
        }
        System.out.printf("Found %d practical numbers between %d and %d:\n%s\n",
                practical.size(), from, to, shorten(practical, 10));

        printPractical(666);
        printPractical(6666);
        printPractical(66666);
        printPractical(672);
        printPractical(720);
        printPractical(222222);
    }

    private static void printPractical(int n) {
        if (isPractical(n))
            System.out.printf("%d is a practical number.\n", n);
        else
            System.out.printf("%d is not a practical number.\n", n);
    }

    private static boolean isPractical(int n) {
        int[] divisors = properDivisors(n);
        for (int i = 1; i < n; ++i) {
            if (!sumOfAnySubset(i, divisors, divisors.length))
                return false;
        }
        return true;
    }

    private static boolean sumOfAnySubset(int n, int[] f, int len) {
        if (len == 0)
            return false;
        int total = 0;
        for (int i = 0; i < len; ++i) {
            if (n == f[i])
                return true;
            total += f[i];
        }
        if (n == total)
            return true;
        if (n > total)
            return false;
        --len;
        int d = n - f[len];
        return (d > 0 && sumOfAnySubset(d, f, len)) || sumOfAnySubset(n, f, len);
    }

    private static int[] properDivisors(int n) {
        List<Integer> divisors = new ArrayList<>();
        divisors.add(1);
        for (int i = 2;; ++i) {
            int i2 = i * i;
            if (i2 > n)
                break;
            if (n % i == 0) {
                divisors.add(i);
                if (i2 != n)
                    divisors.add(n / i);
            }
        }
        int[] result = new int[divisors.size()];
        for (int i = 0; i < result.length; ++i)
            result[i] = divisors.get(i);
        Arrays.sort(result);
        return result;
    }

    private static String shorten(List<Integer> list, int n) {
        StringBuilder str = new StringBuilder();
        int len = list.size(), i = 0;
        if (n > 0 && len > 0)
            str.append(list.get(i++));
        for (; i < n && i < len; ++i) {
            str.append(", ");
            str.append(list.get(i));
        }
        if (len > i + n) {
            if (n > 0)
                str.append(", ...");
            i = len - n;
        }
        for (; i < len; ++i) {
            str.append(", ");
            str.append(list.get(i));
        }
        return str.toString();
    }
}



Python: from itertools import chain, cycle, accumulate, combinations
from typing import List, Tuple



def factors5(n: int) -> List[int]:
    
    def prime_powers(n):
        
        for c in accumulate(chain([2, 1, 2], cycle([2,4]))):
            if c*c > n: break
            if n%c: continue
            d,p = (), c
            while not n%c:
                n,p,d = n//c, p*c, d + (p,)
            yield(d)
        if n > 1: yield((n,))

    r = [1]
    for e in prime_powers(n):
        r += [a*b for a in r for b in e]
    return r[:-1]



def powerset(s: List[int]) -> List[Tuple[int, ...]]:
    
    return chain.from_iterable(combinations(s, r) for r in range(1, len(s)+1))



def is_practical(x: int) -> bool:
    
    if x == 1:
        return True
    if x %2:
        return False  
    f = factors5(x)
    ps = powerset(f)
    found = {y for y in {sum(i) for i in ps}
             if 1 <= y < x}
    return len(found) == x - 1


if __name__ == '__main__':
    n = 333
    p = [x for x in range(1, n + 1) if is_practical(x)]
    print(f"There are {len(p)} Practical numbers from 1 to {n}:")
    print(' ', str(p[:10])[1:-1], '...', str(p[-10:])[1:-1])
    x = 666
    print(f"\nSTRETCH GOAL: {x} is {'not ' if not is_practical(x) else ''}Practical.")