WeixiangYan/CodeTransOcean huggingface dataset:
Task: Untouchable numbers


C++: 
#include <functional>
#include <bitset> 
#include <iostream>
#include <cmath>
using namespace std; using Z0=long long; using Z1=optional<Z0>; using Z2=optional<array<int,3>>; using Z3=function<Z2()>;
const int maxUT{3000000}, dL{(int)log2(maxUT)};
struct uT{
  bitset<maxUT+1>N; vector<int> G{}; array<Z3,int(dL+1)>L{Z3{}}; int sG{0},mUT{};
  void _g(int n,int g){if(g<=mUT){N[g]=false; return _g(n,n+g);}}
  Z1 nxt(const int n){if(n>mUT) return Z1{}; if(N[n]) return Z1(n); return nxt(n+1);}
  Z3 fN(const Z0 n,const Z0 i,int g){return [=]()mutable{if(g<sG && ((n+i)*(1+G[g])-n*G[g]<=mUT)) return Z2{{n,i,g++}}; return Z2{};};}
  Z3 fG(Z0 n,Z0 i,const int g){Z0 e{n+i},l{1},p{1}; return [=]()mutable{n=n*G[g]; p=p*G[g]; l=l+p; i=e*l-n; if(i<=mUT) return Z2{{n,i,g}}; return Z2{};};}
  void fL(Z3 n, int g){for(;;){
    if(auto i=n()){N[(*i)[1]]=false; L[g+1]=fN((*i)[0],(*i)[1],(*i)[2]+1); g=g+1; continue;}
    if(auto i=L[g]()){n=fG((*i)[0],(*i)[1],(*i)[2]); continue;}
    if(g>0) if(auto i=L[g-1]()){ g=g-1; n=fG((*i)[0],(*i)[1],(*i)[2]); continue;}
    if(g>0){ n=[](){return Z2{};}; g=g-1; continue;} break;}
  }
  int count(){int g{0}; for(auto n=nxt(0); n; n=nxt(*n+1)) ++g; return g;}
  uT(const int n):mUT{n}{
    N.set(); N[0]=false; N[1]=false; for(auto n=nxt(0);*n<=sqrt(mUT);n=nxt(*n+1)) _g(*n,*n+*n); for(auto n=nxt(0); n; n=nxt(*n+1)) G.push_back(*n); sG=G.size();
    N.set(); N[0]=false; L[0]=fN(1,0,0); fL([](){return Z2{};},0);
  }
};
Task: Erdős-Nicolas numbers


C++: #include <iomanip>
#include <iostream>
#include <vector>

int main() {
    const int max_number = 100000000;
    std::vector<int> dsum(max_number + 1, 1);
    std::vector<int> dcount(max_number + 1, 1);
    for (int i = 2; i <= max_number; ++i) {
        for (int j = i + i; j <= max_number; j += i) {
            if (dsum[j] == j) {
                std::cout << std::setw(8) << j
                          << " equals the sum of its first " << dcount[j]
                          << " divisors\n";
            }
            dsum[j] += i;
            ++dcount[j];
        }
    }
}
Task: Permuted multiples


C++: #include <array>
#include <iostream>

using digits = std::array<unsigned int, 10>;

digits get_digits(unsigned int n) {
    digits d = {};
    do {
        ++d[n % 10];
        n /= 10;
    } while (n > 0);
    return d;
}


bool same_digits(unsigned int n) {
    digits d = get_digits(n);
    for (unsigned int i = 0, m = n; i < 5; ++i) {
        m += n;
        if (get_digits(m) != d)
            return false;
    }
    return true;
}

int main() {
    for (unsigned int p = 100; ; p *= 10) {
        unsigned int max = (p * 10) / 6;
        for (unsigned int n = p + 2; n <= max; n += 3) {
            if (same_digits(n)) {
                std::cout << " n = " << n << '\n';
                for (unsigned int i = 2; i <= 6; ++i)
                    std::cout << i << "n = " << n * i << '\n';
                return 0;
            }
        }
    }
}
Task: Palindromic gapful numbers


C++: #include <iostream>
#include <cstdint>

typedef uint64_t integer;

integer reverse(integer n) {
    integer rev = 0;
    while (n > 0) {
        rev = rev * 10 + (n % 10);
        n /= 10;
    }
    return rev;
}



class palindrome_generator {
public:
    palindrome_generator(int digit) : power_(10), next_(digit * power_ - 1),
        digit_(digit), even_(false) {}
    integer next_palindrome() {
        ++next_;
        if (next_ == power_ * (digit_ + 1)) {
            if (even_)
                power_ *= 10;
            next_ = digit_ * power_;
            even_ = !even_;
        }
        return next_ * (even_ ? 10 * power_ : power_)
            + reverse(even_ ? next_ : next_/10);
    }
private:
    integer power_;
    integer next_;
    int digit_;
    bool even_;
};

bool gapful(integer n) {
    integer m = n;
    while (m >= 10)
        m /= 10;
    return n % (n % 10 + 10 * m) == 0;
}

template<size_t len>
void print(integer (&array)[9][len]) {
    for (int digit = 1; digit < 10; ++digit) {
        std::cout << digit << ":";
        for (int i = 0; i < len; ++i)
            std::cout << ' ' << array[digit - 1][i];
        std::cout << '\n';
    }
}

int main() {
    const int n1 = 20, n2 = 15, n3 = 10;
    const int m1 = 100, m2 = 1000;

    integer pg1[9][n1];
    integer pg2[9][n2];
    integer pg3[9][n3];

    for (int digit = 1; digit < 10; ++digit) {
        palindrome_generator pgen(digit);
        for (int i = 0; i < m2; ) {
            integer n = pgen.next_palindrome();
            if (!gapful(n))
                continue;
            if (i < n1)
                pg1[digit - 1][i] = n;
            else if (i < m1 && i >= m1 - n2)
                pg2[digit - 1][i - (m1 - n2)] = n;
            else if (i >= m2 - n3)
                pg3[digit - 1][i - (m2 - n3)] = n;
            ++i;
        }
    }

    std::cout << "First " << n1 << " palindromic gapful numbers ending in:\n";
    print(pg1);

    std::cout << "\nLast " << n2 << " of first " << m1 << " palindromic gapful numbers ending in:\n";
    print(pg2);

    std::cout << "\nLast " << n3 << " of first " << m2 << " palindromic gapful numbers ending in:\n";
    print(pg3);

    return 0;
}
Task: Prime triangle


C++: #include <cassert>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>

bool is_prime(unsigned int n) {
    assert(n > 0 && n < 64);
    return (1ULL << n) & 0x28208a20a08a28ac;
}

template <typename Iterator>
bool prime_triangle_row(Iterator begin, Iterator end) {
    if (std::distance(begin, end) == 2)
        return is_prime(*begin + *(begin + 1));
    for (auto i = begin + 1; i + 1 != end; ++i) {
        if (is_prime(*begin + *i)) {
            std::iter_swap(i, begin + 1);
            if (prime_triangle_row(begin + 1, end))
                return true;
            std::iter_swap(i, begin + 1);
        }
    }
    return false;
}

template <typename Iterator>
void prime_triangle_count(Iterator begin, Iterator end, int& count) {
    if (std::distance(begin, end) == 2) {
        if (is_prime(*begin + *(begin + 1)))
            ++count;
        return;
    }
    for (auto i = begin + 1; i + 1 != end; ++i) {
        if (is_prime(*begin + *i)) {
            std::iter_swap(i, begin + 1);
            prime_triangle_count(begin + 1, end, count);
            std::iter_swap(i, begin + 1);
        }
    }
}

template <typename Iterator>
void print(Iterator begin, Iterator end) {
    if (begin == end)
        return;
    auto i = begin;
    std::cout << std::setw(2) << *i++;
    for (; i != end; ++i)
        std::cout << ' ' << std::setw(2) << *i;
    std::cout << '\n';
}

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    for (unsigned int n = 2; n < 21; ++n) {
        std::vector<unsigned int> v(n);
        std::iota(v.begin(), v.end(), 1);
        if (prime_triangle_row(v.begin(), v.end()))
            print(v.begin(), v.end());
    }
    std::cout << '\n';
    for (unsigned int n = 2; n < 21; ++n) {
        std::vector<unsigned int> v(n);
        std::iota(v.begin(), v.end(), 1);
        int count = 0;
        prime_triangle_count(v.begin(), v.end(), count);
        if (n > 2)
            std::cout << ' ';
        std::cout << count;
    }
    std::cout << '\n';
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration(end - start);
    std::cout << "\nElapsed time: " << duration.count() << " seconds\n";
}
Task: Ormiston pairs


C++: #include <array>
#include <iomanip>
#include <iostream>
#include <utility>

#include <primesieve.hpp>

class ormiston_pair_generator {
public:
    ormiston_pair_generator() { prime_ = pi_.next_prime(); }
    std::pair<uint64_t, uint64_t> next_pair() {
        for (;;) {
            uint64_t prime = prime_;
            auto digits = digits_;
            prime_ = pi_.next_prime();
            digits_ = get_digits(prime_);
            if (digits_ == digits)
                return std::make_pair(prime, prime_);
        }
    }

private:
    static std::array<int, 10> get_digits(uint64_t n) {
        std::array<int, 10> result = {};
        for (; n > 0; n /= 10)
            ++result[n % 10];
        return result;
    }
    primesieve::iterator pi_;
    uint64_t prime_;
    std::array<int, 10> digits_;
};

int main() {
    ormiston_pair_generator generator;
    int count = 0;
    std::cout << "First 30 Ormiston pairs:\n";
    for (; count < 30; ++count) {
        auto [p1, p2] = generator.next_pair();
        std::cout << '(' << std::setw(5) << p1 << ", " << std::setw(5) << p2
                  << ')' << ((count + 1) % 3 == 0 ? '\n' : ' ');
    }
    std::cout << '\n';
    for (uint64_t limit = 1000000; limit <= 1000000000; ++count) {
        auto [p1, p2] = generator.next_pair();
        if (p1 > limit) {
            std::cout << "Number of Ormiston pairs < " << limit << ": " << count
                      << '\n';
            limit *= 10;
        }
    }
}
Task: Earliest difference between prime gaps


C++: #include <iostream>
#include <locale>
#include <unordered_map>

#include <primesieve.hpp>

class prime_gaps {
public:
    prime_gaps() { last_prime_ = iterator_.next_prime(); }
    uint64_t find_gap_start(uint64_t gap);
private:
    primesieve::iterator iterator_;
    uint64_t last_prime_;
    std::unordered_map<uint64_t, uint64_t> gap_starts_;
};

uint64_t prime_gaps::find_gap_start(uint64_t gap) {
    auto i = gap_starts_.find(gap);
    if (i != gap_starts_.end())
        return i->second;
    for (;;) {
        uint64_t prev = last_prime_;
        last_prime_ = iterator_.next_prime();
        uint64_t diff = last_prime_ - prev;
        gap_starts_.emplace(diff, prev);
        if (gap == diff)
            return prev;
    }
}

int main() {
    std::cout.imbue(std::locale(""));
    const uint64_t limit = 100000000000;
    prime_gaps pg;
    for (uint64_t pm = 10, gap1 = 2;;) {
        uint64_t start1 = pg.find_gap_start(gap1);
        uint64_t gap2 = gap1 + 2;
        uint64_t start2 = pg.find_gap_start(gap2);
        uint64_t diff = start2 > start1 ? start2 - start1 : start1 - start2;
        if (diff > pm) {
            std::cout << "Earliest difference > " << pm
                      << " between adjacent prime gap starting primes:\n"
                      << "Gap " << gap1 << " starts at " << start1 << ", gap "
                      << gap2 << " starts at " << start2 << ", difference is "
                      << diff << ".\n\n";
            if (pm == limit)
                break;
            pm *= 10;
        } else {
            gap1 = gap2;
        }
    }
}
Task: Anaprimes


C++: #include <array>
#include <iostream>
#include <map>
#include <vector>

#include <primesieve.hpp>

using digit_set = std::array<int, 10>;

digit_set get_digits(uint64_t n) {
    digit_set result = {};
    for (; n > 0; n /= 10)
        ++result[n % 10];
    return result;
}

int main() {
    std::cout.imbue(std::locale(""));
    primesieve::iterator pi;
    using map_type =
        std::map<digit_set, std::vector<uint64_t>, std::greater<digit_set>>;
    map_type anaprimes;
    for (uint64_t limit = 1000; limit <= 10000000000;) {
        uint64_t prime = pi.next_prime();
        if (prime > limit) {
            size_t max_length = 0;
            std::vector<map_type::iterator> groups;
            for (auto i = anaprimes.begin(); i != anaprimes.end(); ++i) {
                if (i->second.size() > max_length) {
                    groups.clear();
                    max_length = i->second.size();
                }
                if (max_length == i->second.size())
                    groups.push_back(i);
            }
            std::cout << "Largest group(s) of anaprimes before " << limit
                      << ": " << max_length << " members:\n";
            for (auto i : groups) {
                std::cout << "  First: " << i->second.front()
                          << "  Last: " << i->second.back() << '\n';
            }
            std::cout << '\n';
            anaprimes.clear();
            limit *= 10;
        }
        anaprimes[get_digits(prime)].push_back(prime);
    }
}
Task: Numbers which are the cube roots of the product of their proper divisors


C++: #include <iomanip>
#include <iostream>

unsigned int divisor_count(unsigned int n) {
    unsigned int total = 1;
    for (; (n & 1) == 0; n >>= 1)
        ++total;
    for (unsigned int p = 3; p * p <= n; p += 2) {
        unsigned int count = 1;
        for (; n % p == 0; n /= p)
            ++count;
        total *= count;
    }
    if (n > 1)
        total *= 2;
    return total;
}

int main() {
    std::cout.imbue(std::locale(""));
    std::cout << "First 50 numbers which are the cube roots of the products of "
                 "their proper divisors:\n";
    for (unsigned int n = 1, count = 0; count < 50000; ++n) {
        if (n == 1 || divisor_count(n) == 8) {
            ++count;
            if (count <= 50)
                std::cout << std::setw(3) << n
                          << (count % 10 == 0 ? '\n' : ' ');
            else if (count == 500 || count == 5000 || count == 50000)
                std::cout << std::setw(6) << count << "th: " << n << '\n';
        }
    }
}
Task: Ruth-Aaron numbers


C++: #include <iomanip>
#include <iostream>

int prime_factor_sum(int n) {
    int sum = 0;
    for (; (n & 1) == 0; n >>= 1)
        sum += 2;
    for (int p = 3, sq = 9; sq <= n; p += 2) {
        for (; n % p == 0; n /= p)
            sum += p;
        sq += (p + 1) << 2;
    }
    if (n > 1)
        sum += n;
    return sum;
}

int prime_divisor_sum(int n) {
    int sum = 0;
    if ((n & 1) == 0) {
        sum += 2;
        n >>= 1;
        while ((n & 1) == 0)
            n >>= 1;
    }
    for (int p = 3, sq = 9; sq <= n; p += 2) {
        if (n % p == 0) {
            sum += p;
            n /= p;
            while (n % p == 0)
                n /= p;
        }
        sq += (p + 1) << 2;
    }
    if (n > 1)
        sum += n;
    return sum;
}

int main() {
    const int limit = 30;
    int dsum1 = 0, fsum1 = 0, dsum2 = 0, fsum2 = 0;

    std::cout << "First " << limit << " Ruth-Aaron numbers (factors):\n";
    for (int n = 2, count = 0; count < limit; ++n) {
        fsum2 = prime_factor_sum(n);
        if (fsum1 == fsum2) {
            ++count;
            std::cout << std::setw(5) << n - 1
                      << (count % 10 == 0 ? '\n' : ' ');
        }
        fsum1 = fsum2;
    }

    std::cout << "\nFirst " << limit << " Ruth-Aaron numbers (divisors):\n";
    for (int n = 2, count = 0; count < limit; ++n) {
        dsum2 = prime_divisor_sum(n);
        if (dsum1 == dsum2) {
            ++count;
            std::cout << std::setw(5) << n - 1
                      << (count % 10 == 0 ? '\n' : ' ');
        }
        dsum1 = dsum2;
    }

    dsum1 = 0, fsum1 = 0, dsum2 = 0, fsum2 = 0;
    for (int n = 2;; ++n) {
        int fsum3 = prime_factor_sum(n);
        if (fsum1 == fsum2 && fsum2 == fsum3) {
            std::cout << "\nFirst Ruth-Aaron triple (factors): " << n - 2
                      << '\n';
            break;
        }
        fsum1 = fsum2;
        fsum2 = fsum3;
    }
    for (int n = 2;; ++n) {
        int dsum3 = prime_divisor_sum(n);
        if (dsum1 == dsum2 && dsum2 == dsum3) {
            std::cout << "\nFirst Ruth-Aaron triple (divisors): " << n - 2
                      << '\n';
            break;
        }
        dsum1 = dsum2;
        dsum2 = dsum3;
    }
}
Task: Permutations with some identical elements


C++: #include <algorithm>
#include <iostream>

int main() {
    std::string str("AABBBC");
    int count = 0;
    do {
        std::cout << str << (++count % 10 == 0 ? '\n' : ' ');
    } while (std::next_permutation(str.begin(), str.end()));
}
Task: Pan base non-primes


C++: #include <algorithm>
#include <cassert>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>

bool is_prime(uint64_t n) {
    if (n < 2)
        return false;
    if (n % 2 == 0)
        return n == 2;
    if (n % 3 == 0)
        return n == 3;
    if (n % 5 == 0)
        return n == 5;
    static constexpr uint64_t wheel[] = {4, 2, 4, 2, 4, 6, 2, 6};
    for (uint64_t p = 7;;) {
        for (uint64_t w : wheel) {
            if (p * p > n)
                return true;
            if (n % p == 0)
                return false;
            p += w;
        }
    }
}

std::vector<uint64_t> digits(uint64_t n) {
    std::vector<uint64_t> d;
    for (uint64_t m = n; m > 0; m /= 10)
        d.push_back(m % 10);
    reverse(d.begin(), d.end());
    return d;
}

template <typename iterator> auto gcd(iterator begin, iterator end) {
    assert(begin != end);
    auto result = *begin++;
    for (; begin != end; ++begin)
        result = std::gcd(result, *begin);
    return result;
}

template <typename number, typename iterator>
number polyval(iterator begin, iterator end, number value) {
    number n = 0;
    for (auto i = begin; i != end; ++i)
        n = n * value + *i;
    return n;
}

bool is_pan_base_non_prime(uint64_t n) {
    if (n < 10)
        return !is_prime(n);
    if (n > 10 && n % 10 == 0)
        return true;
    auto d = digits(n);
    if (gcd(d.begin(), d.end()) > 1)
        return true;
    auto max_digit = *std::max_element(d.begin(), d.end());
    for (uint64_t base = max_digit + 1; base <= n; ++base) {
        if (is_prime(polyval(d.begin(), d.end(), base)))
            return false;
    }
    return true;
}

int main() {
    std::vector<uint64_t> pbnp;
    const uint64_t limit = 10000;
    for (uint64_t n = 2; n <= limit; ++n) {
        if (is_pan_base_non_prime(n))
            pbnp.push_back(n);
    }

    std::cout << "First 50 pan-base composites:\n";
    for (size_t i = 0; i < 50; ++i) {
        std::cout << std::setw(3) << pbnp[i]
                  << ((i + 1) % 10 == 0 ? '\n' : ' ');
    }

    std::cout << "\nFirst 20 odd pan-base composites:\n";
    for (size_t i = 0, count = 0; count < 20; ++i) {
        if (pbnp[i] % 2 == 1) {
            ++count;
            std::cout << std::setw(3) << pbnp[i]
                      << (count % 10 == 0 ? '\n' : ' ');
        }
    }

    size_t total = pbnp.size();
    size_t odd = std::count_if(pbnp.begin(), pbnp.end(),
                               [](uint64_t n) { return n % 2 == 1; });
    std::cout << "\nCount of pan-base composites up to and including " << limit
              << ": " << total << '\n';
    auto percent = (100.0 * odd) / total;
    std::cout << std::fixed;
    std::cout << "Percent odd  up to and including " << limit << ": " << percent
              << '\n';
    std::cout << "Percent even up to and including " << limit << ": "
              << 100.0 - percent << '\n';
}
Task: Sieve of Pritchard


C++: 



#include <cstring>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctime>

void Extend (uint32_t w[], uint32_t &w_end, uint32_t &length, uint32_t n, bool d[], uint32_t &w_end_max) {
    
    uint32_t i, j, x;
    i = 0; j = w_end;
    x = length + 1; 
    while (x <= n) {
        w[++j] = x; 
        d[x] = false;
        x = length + w[++i];
    }
    length = n; w_end = j;
    if (w_end > w_end_max) w_end_max = w_end;
}

void Delete (uint32_t w[], uint32_t length, uint32_t p, bool d[], uint32_t &imaxf) {
    
    uint32_t i, x;
    i = 0;
    x = p; 
    while (x <= length) {
        d[x] = true; 
        x = p*w[++i];
    }
    imaxf = i-1;
}

void Compress(uint32_t w[], bool d[], uint32_t to, uint32_t &w_end) {
    
    uint32_t i, j;
    j = 0;
    for (i=1; i <= to; i++) {
        if (!d[w[i]]) {
            w[++j] = w[i];
        }
    }
    if (to == w_end) {
        w_end = j;
    } else {
        for (uint32_t k=j+1; k <= to; k++) w[k] = 0;
    }
}

void Sift(uint32_t N, bool printPrimes, uint32_t &nrPrimes, uint32_t &vBound) {
    
    uint32_t *w = new uint32_t[N/4+5];
    bool *d = new bool[N+1];
    uint32_t w_end, length;
    
    
    
    
    uint32_t w_end_max, p, imaxf;
    
    w_end = 0; w[0] = 1;
    w_end_max = 0;
    length = 2;
    
    nrPrimes = 1;
    if (printPrimes) printf("%d", 2);
    p = 3;
    
    
    while (p*p <= N) {
        
        nrPrimes++;
        if (printPrimes) printf(" %d", p);
        if (length < N) {
            
            Extend (w, w_end, length, std::min(p*length,N), d, w_end_max);
        }
        Delete(w, length, p, d, imaxf);
        Compress(w, d, (length < N ? w_end : imaxf), w_end);
        
        p = w[1];
        if (p == 0) break; 
        
    }
    if (length < N) {
        
        Extend (w, w_end, length, N, d, w_end_max);
    }
    
    for (uint32_t i=1; i <= w_end; i++) {
        if (w[i] == 0 || d[w[i]]) continue;
        if (printPrimes) printf(" %d", w[i]);
        nrPrimes++;
    }
    vBound = w_end_max+1;
}

int main (int argc, char *argw[]) {
    bool error = false;
    bool printPrimes = false;
    uint32_t N, nrPrimes, vBound;
    if (argc == 3) {
        if (strcmp(argw[2], "-p") == 0) {
            printPrimes = true;
            argc--;
        } else {
            error = true;
        }
    }
    if (argc == 2) {
        N = atoi(argw[1]);
        if (N < 2 || N > 1000000000) error = true;
    } else {
        error = true;
    }
    if (error) {
        printf("call with: %s N -p where 2 <= N <= 1000000000 and -p to print the primes is optional \n", argw[0]);
        exit(1);
    }
    int start_s = clock();
    Sift(N, printPrimes, nrPrimes, vBound);
    int stop_s=clock();
    printf("\n%d primes up to %lu found in %.3f ms using array w[%d]\n", nrPrimes,
      (unsigned long)N, (stop_s-start_s)*1E3/double(CLOCKS_PER_SEC), vBound);
}
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;
}