Project Euler 28

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


スパイラルの座標を次々に出すクラスを作った。


itertools.h

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

using namespace std;
using namespace itertools;

typedef tuple<int,int>  Point;

class cSpiral {
    Point   pt;
    
public:
    cSpiral() : pt(make_tuple(0, 0)) { }
    Point next() {
        Point   prev_pt = pt;
        int     x = fst(pt);
        int     y = snd(pt);
        if(y >= 0 && -y <= x && x <= y)
            pt = make_tuple(x + 1, y);
        else if(x > 0 && y > -x)
            pt = make_tuple(x, y - 1);
        else if(y < 0 && x > y)
            pt = make_tuple(x - 1, y);
        else
            pt = make_tuple(x, y + 1);
        return prev_pt;
    }
    bool exists_next() { return true; }
};

bool is_on_diagonal(Point pt) {
    return abs(fst(pt)) == abs(snd(pt));
}

int main() {
    const int   N = 1001;
    typedef tuple<int,Point>    Comb;
    cout << sum(takewhile([N] (int n) { return n <= N * N; },
            map(fst<int,Point>,
            filter([] (Comb x) { return is_on_diagonal(snd(x)); },
            zip(itertools::count<>(1), cSpiral()))))) << endl;
}