http://projecteuler.net/index.php?section=problems&id=32
重複は数えないからsetを使う。そして和を取る。iterableでsetを引数に取れるようにしたが、よく考えたらaccumulateを使えばいいだけだった。これがnumericにあることをいつも忘れる。
#include <iostream> #include <set> #include <numeric> #include "itertools.h" using namespace std; using namespace itertools; int pow(int n, int e) { return e == 0 ? 1 : n * pow(n, e - 1); } const int N = 9; const int M = (N + 1) / 2; // 左辺の合計の桁数 // get<k>(x)のkを実行時に変更するため int get(int k, tuple<int,int,int> x) { return k == 0 ? get<0>(x) : (k == 1 ? get<1>(x) : get<2>(x)); } bool is_valid(tuple<int,int,int> x) { int n = get<2>(x); // ビットを立てる return pow(10, N - M - 1) <= n && n < pow(10, N - M) && reduce([] (int x, int d) { return x | (1 << d); }, map(snd<int,int>, product(range<>(3), [&x] (int k) { return digits(get(k, x)); })) , 0) == (2 << N) - 2; } vector<int> list_pandigital(int n) { return list(map([] (tuple<int,int,int> x) { return get<2>(x); }, filter(is_valid, map([] (tuple<int,int> x) { return make_tuple(fst(x), snd(x), fst(x) * snd(x)); }, product(range<>(pow(10, n - 1), pow(10, n)), range<>(pow(10, M - 1 - n), pow(10, M - n))))))); } int main() { set<int> s; for(int n = 1; n <= M / 2; n++) iter([&s] (int m) { s.insert(m); }, iterable(list_pandigital(n))); cout << accumulate(s.begin(), s.end(), 0) << endl; }