Project Euler 37

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


右から短くしていっても素数のままの数を求めるのと左からのもののアルゴリズムがほとんど同じなので、テンプレートを使って共通化できるところは同じコードを使うようにしたら、却ってコードが長くなった。


itertools.h

#include <iostream>
#include <set>
#include "primes.h"

using namespace std;
using namespace itertools;

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

template<typename T>
vector<int> get_truncable(const vector<int>& ps, T& f) {
    return list(filter(primes::is_prime,
            map(f, product(iterable(ps), range<>(1, 10)))));
}

vector<int> get_right_truncable(const vector<int>& ps, int n) {
    int m = pow(10, n);
    return get_truncable(ps,
            [&] (tuple<int,int> x) { return fst(x) + snd(x) * m; });
}

vector<int> get_left_truncable(const vector<int>& ps, int n) {
    return get_truncable(ps,
            [] (tuple<int,int> x) { return fst(x) * 10 + snd(x); });
}

vector<int> intersection(const vector<int>& v1, const vector<int>& v2) {
    return list(filter([&] (int n)
            { return find(v2.begin(), v2.end(), n) != v2.end(); },
            iterable(v1)));
}

int main() {
    vector<int> ps_right = list(filter(primes::is_prime, range<>(2, 10)));
    vector<int> ps_left = ps_right;
    
    int s = 0;
    for(int n = 1; !ps_right.empty() && !ps_left.empty(); n++) {
        ps_right = get_right_truncable(ps_right, n);
        ps_left  = get_left_truncable(ps_left, n);
        s += sum(iterable(intersection(ps_right, ps_left)));
    }
    cout << s << endl;
}