Task: Practical numbers


C++: #include <algorithm>
#include <iostream>
#include <numeric>
#include <sstream>
#include <vector>


template <typename iterator>
bool sum_of_any_subset(int n, iterator begin, iterator end) {
    if (begin == end)
        return false;
    if (std::find(begin, end, n) != end)
        return true;
    int total = std::accumulate(begin, end, 0);
    if (n == total)
        return true;
    if (n > total)
        return false;
    --end;
    int d = n - *end;
    return (d > 0 && sum_of_any_subset(d, begin, end)) ||
           sum_of_any_subset(n, begin, end);
}


std::vector<int> factors(int n) {
    std::vector<int> f{1};
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            f.push_back(i);
            if (i * i != n)
                f.push_back(n / i);
        }
    }
    std::sort(f.begin(), f.end());
    return f;
}

bool is_practical(int n) {
    std::vector<int> f = factors(n);
    for (int i = 1; i < n; ++i) {
        if (!sum_of_any_subset(i, f.begin(), f.end()))
            return false;
    }
    return true;
}

std::string shorten(const std::vector<int>& v, size_t n) {
    std::ostringstream out;
    size_t size = v.size(), i = 0;
    if (n > 0 && size > 0)
        out << v[i++];
    for (; i < n && i < size; ++i)
        out << ", " << v[i];
    if (size > i + n) {
        out << ", ...";
        i = size - n;
    }
    for (; i < size; ++i)
        out << ", " << v[i];
    return out.str();
}

int main() {
    std::vector<int> practical;
    for (int n = 1; n <= 333; ++n) {
        if (is_practical(n))
            practical.push_back(n);
    }
    std::cout << "Found " << practical.size() << " practical numbers:\n"
              << shorten(practical, 10) << '\n';
    for (int n : {666, 6666, 66666, 672, 720, 222222})
        std::cout << n << " is " << (is_practical(n) ? "" : "not ")
                  << "a practical number.\n";
    return 0;
}



Go: package main

import (
    "fmt"
    "rcu"
)

func powerset(set []int) [][]int {
    if len(set) == 0 {
        return [][]int{{}}
    }
    head := set[0]
    tail := set[1:]
    p1 := powerset(tail)
    var p2 [][]int
    for _, s := range powerset(tail) {
        h := []int{head}
        h = append(h, s...)
        p2 = append(p2, h)
    }
    return append(p1, p2...)
}

func isPractical(n int) bool {
    if n == 1 {
        return true
    }
    divs := rcu.ProperDivisors(n)
    subsets := powerset(divs)
    found := make([]bool, n) 
    count := 0
    for _, subset := range subsets {
        sum := rcu.SumInts(subset)
        if sum > 0 && sum < n && !found[sum] {
            found[sum] = true
            count++
            if count == n-1 {
                return true
            }
        }
    }
    return false
}

func main() {
    fmt.Println("In the range 1..333, there are:")
    var practical []int
    for i := 1; i <= 333; i++ {
        if isPractical(i) {
            practical = append(practical, i)
        }
    }
    fmt.Println(" ", len(practical), "practical numbers")
    fmt.Println("  The first ten are", practical[0:10])
    fmt.Println("  The final ten are", practical[len(practical)-10:])
    fmt.Println("\n666 is practical:", isPractical(666))
}