C#でProject Euler(8) Dictionary

Pythonの辞書の代替になるコンテナはDictionaryです。Problem 27を考えてみましょう。Pythonならこんな感じです。

from itertools import *
import time

memo = { }
def IsPrime(n):
    if n < 2:
        return False
    elif n in memo:
        return memo[n]
    
    b = all(n % p != 0 for p in takewhile(lambda p: p * p <= n, count(2)))
    memo[n] = b
    return b

def length(a, b):
    return next(dropwhile(lambda n: IsPrime(n * (n + a) + b), count()))

t0 = time.clock()
t = max((length(a, b), a, b) for a, b in product(range(-999, 1000), repeat = 2))
print t[1] * t[2]

素数判定にメモ化を使っており、メモ化に辞書を使っています。これをC#にすると、

using System;
using System.Collections.Generic;
using System.Linq;

class e027 {
    static IEnumerable<int> count(int init = 0, int d = 1) {
        while(true) {
            yield return init;
            init += d;
        }
    }
    
    static Dictionary<int,bool> memo = new Dictionary<int,bool>();
    static bool IsPrime(int n) {
        if(n < 2)
            return false;
        if(memo.ContainsKey(n))
            return memo[n];
        var b = count(2).TakeWhile(p => p * p <= n).All(p => n % p != 0);
        memo[n] = b;
        return b;
    }
    
    static int length(int a, int b) {
        return count().TakeWhile(n => IsPrime(n * (n + a) + b)).Count();
    }
    
    static void Main(string[] args) {
        var sw = new System.Diagnostics.Stopwatch();
        sw.Start();
        
        var g = from a in Enumerable.Range(-999, 1999)
                from b in Enumerable.Range(-999, 1999)
                select Tuple.Create(length(a, b), a, b);
        var t = g.Max();
        Console.WriteLine(t);
        Console.WriteLine(t.Item2 * t.Item3);
        
        sw.Stop();
        Console.WriteLine(sw.Elapsed.ToString());
    }
}

詳しくは、公式を参照。
Pythonと同様にタプルを使っていますが、使いにくいですね。