Project Euler 50

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


unfoldを作ってみた。


itertools.h
primes.h

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

using namespace std;
using namespace itertools;

const int   N = 1000000;

template<typename T, typename U, typename V>
class cUnfold {
    T&  fun;
    U   stat;
    
public:
    cUnfold(T& f, U init) : fun(f), stat(init) { }
    V next() {
        auto    x = fun(stat);
        stat = snd(x);
        return fst(x);
    }
    bool exists_next() { return true; }
};

template<typename T, typename U>
auto unfold(T& f, U init) -> cUnfold<T,U,decltype(fst(f(init)))> {
    return cUnfold<T,U,decltype(fst(f(init)))>(f, init);
}

typedef tuple<int,int>  t_int;

// 最も長い和が素数になる素数列
t_int base_length(int k) {
    auto    ps = primes::genPrimes();
    for(int i = 0; i < k; i++) ps.next();
    auto    g = unfold([&ps] (int s) -> t_int
                            { int s1 = s + ps.next();
                            return t_int(s1, s1); }, 0);
    vector<int> v = list(takewhile([] (int n) { return n < N; },g));
    int n = fst(last(filter([] (t_int t)
                            { return primes::is_prime(snd(t)); },
            zip(itertools::count<>(1), iterable(v)))));
    return t_int(v.size(), n);
}

int sum_max_length(int k, int L) {
    auto    ps = primes::genPrimes();
    for(int i = 0; i < k; i++) ps.next();
    return sum(map(snd<int,int>,
                (takewhile([L] (t_int t) { return fst(t) <= L; },
                zip(itertools::count<>(1), ps)))));
}

int main() {
    int max_k = -1;
    int max_length = 0;
    for(int k = 0; k < 10; k++) {
        t_int   x = base_length(k);
        if(snd(x) > max_length) {
            max_length = snd(x);
            max_k = k;
        }
        if(fst(x) < max_length) {
            cout << sum_max_length(max_k, max_length) << endl;
            break;
        }
    }
}