Project Euler 45

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


2つのiterableが一致する値を出すクラスを作る。
多角数を出すiterableがなかなか書けなかった。
場合分けしているのは、こうしないとギリギリintの範囲に収まらないから。long longにしておけばこんなことをする必要は無い。

template<int N>
int polynomial(int n) {
    if(n % 2 == 0)
        return ((N - 2) * n + 4 - N) * (n / 2);
    else
        return ((N - 2) * n + 4 - N) / 2 * n;
}

int main() {
    using namespace itertools;
    
    auto    g1 = count<>(1);
    auto    g2 = count<>(1);
    auto    pen = map(polynomial<5>, g1);
    auto    hex = map(polynomial<6>, g2);
    ...
}


itertools.h

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

template<int N>
int polynomial(int n) {
    if(n % 2 == 0)
        return ((N - 2) * n + 4 - N) * (n / 2);
    else
        return ((N - 2) * n + 4 - N) / 2 * n;
}

template<typename T, typename U>
class cFindCoincident {
    T&  gen1;
    U&  gen2;
    int v1;
    int v2;
    
public:
    cFindCoincident(T& g1, U& g2) : gen1(g1), gen2(g2) {
        v1 = gen1.next();
        v2 = gen2.next();
    }
    int next() {
        if(v1 == v2) {
            int ret = v1;
            v1 = gen1.next();
            v2 = gen2.next();
            return ret;
        }
        else if(v1 < v2) {
            v1 = gen1.next();
            return next();
        }
        else {
            v2 = gen2.next();
            return next();
        }
    }
    bool exists_next() { return true; }
};

template<typename T, typename U>
cFindCoincident<T,U> find_coincident(T& g1, U& g2) {
    return cFindCoincident<T,U>(g1, g2);
}

int main() {
    using namespace itertools;
    
    auto    g1 = count<>(1);
    auto    g2 = count<>(1);
    auto    pen = map(polynomial<5>, g1);
    auto    hex = map(polynomial<6>, g2);
    auto    g = find_coincident(pen, hex);
    g.next();
    g.next();
    std::cout << g.next() << std::endl;
}