http://projecteuler.net/index.php?section=problems&id=14
Haskellで書くとこんな感じ。
import Data.List next n = if mod n 2 == 0 then div n 2 else 3 * n + 1 chain_length n = head [ k | (k,m) <- zip [1..] (iterate next n), m == 1 ] limit = 10^6 - 1 longer x y = if snd x >= snd y then x else y main = print (fst (foldl1' longer [ (n,chain_length n) | n <- [1..limit] ]))
iterateは、
iterate f x = [ x, f x, f . f x, … ]
で、この問題の場合で、
iterate next 13 = [ 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 1, … ]
これをitertools.hに書き加えて利用した。
#include <iostream> #include "itertools.h" using namespace std; using namespace itertools; typedef long long int64; long long next(int64 n) { if(n % 2 == 0) return n / 2; else return 3 * n + 1; } int chain_length(int n) { return fst(head(filter([] (tuple<int,int64> x) { return snd(x) == 1; }, zip(count<>(1), iterate(next, (int64)n))))); } tuple<int,int> longer(tuple<int,int> x, tuple<int,int> y) { return snd(x) >= snd(y) ? x : y; } int main() { const int N = (int)1e6; cout << fst(reduce1(longer, map([] (int n) { return make_tuple(n, chain_length(n)); }, range<>(1, N + 1)))) << endl; }
Haskellの半分以下の実行時間だった。