Project Euler 43

http://projecteuler.net/index.php?section=problems&id=43


最後に頭に数字をつけるところは、45からその数の各桁の合計を引けばよい。


itertools.h

#include <iostream>
#include "itertools.h"

using namespace std;
using namespace itertools;

const int   primes_rev[] = { 17, 13, 11, 7, 5, 3, 2 };

bool is_pandigital(int n, int m) {
    int f = 0;
    for(int k = 0; k < m; k++) {
        int d = n % 10;
        if(f & (1 << d))
            return false;
        f |= 1 << d;
        n /= 10;
    }
    return true;
}

int pow(int n, int e) {
    return e == 0 ? 1 : n * pow(n, e - 1);
}

vector<int> next_pan(vector<int>& v0, int k) {
    int p = primes_rev[k];
    int m = pow(10, k);
    int m2 = m * 100;
    return list(filter([&] (int n)
                    { return n / m % p == 0 && is_pandigital(n, k + 3); },
            map([&] (tuple<int,int> x) { return fst(x) * m2 + snd(x); },
            product(range<>(10), iterable(v0)))));
}

long long complement(int n) {
    int d = 45 - sum(digits(n));
    return d * (long long)pow(10, 9) + n;
}

int main() {
    auto    g = filter([] (int n) { return is_pandigital(n, 3); },
                                            range<>(17, 1000, 17));
    auto    v = reduce(next_pan, range<>(1, 7), list(g));
    cout << sum(map(complement, iterable(v))) << endl;
}