Project Euler 49

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


重複組合せを出し、それぞれについて順列を出し、その中の2つずつを取って等差数列を作って次の口が順列にあるか調べて、あればそれぞれ素数か調べる。


itertools.h
primes.h

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

using namespace std;
using namespace itertools;

template<typename T>
ostream& operator <<(ostream& os, const vector<T>& v) {
    for(int k = 0; k < (int)v.size(); k++)
        os << v[k] << " ";
    return os;
}

template<typename T>
class cRepeatedCombination {
    const vector<T> vmap;
    vector<T>   ret;
    vector<int> ref;
    int         length;
    bool        first;
    
public:
    cRepeatedCombination(const vector<T>& v, int n) : vmap(v), length(n) {
        ret = vector<int>(length, v.front());
        ref = vector<int>(length, 0);
        first = true;
    }
    vector<T> next() {
        if(!first) {
            const int   p = pos(length - 1);
            ref[p]++;
            ret[p] = vmap[ref[p]];
            reset(ref[p], p + 1);
        }
        
        first = false;
        return ret;
    }
    bool exists_next() {
        return exists();
    }
    
private:
    int pos(int p) {
        if(ref[p] != vmap.size() - 1) return p;
        else return pos(p - 1);
    }
    void reset(int n, int p) {
        if(p == length) return;
        ref[p] = n;
        ret[p] = vmap[n];
        reset(n, p + 1);
    }
    bool exists(int p = 0) {
        if(p == length) return false;
        else if(ref[p] != vmap.size() - 1) return true;
        else return exists(p + 1);
    }
};

template<typename T>
cRepeatedCombination<T> repeated_combination(const vector<T>& v, int n) {
    return cRepeatedCombination<T>(v, n);
}

const int   N = 4;
const int   M = 1000;

void diff_primes(vector<int> v) {
    using namespace primes;
    
    set<int>    s;
    auto    g = perm(v);
    while(g.exists_next()) {
        int n = to_number(iterable(g.next()));
        if(n >= M)
            s.insert(n);
    }
    for(auto p = s.begin(); p != s.end(); ++p) {
        int n1 = *p;
        if(!is_prime(n1))
            continue;
        for(auto q = s.begin(); q != s.end(); ++q) {
            int n2 = *q;
            int n3 = n2 * 2 - n1;
            if(n1 < n2 && s.find(n3) != s.end()
                    && is_prime(n2) && is_prime(n3))
                cout << n1 << n2 << n3 << endl;
        }
    }
}

int main() {
    auto    rc = repeated_combination(list(range<>(10)), N);
    iter(diff_primes, rc);
}