Project Euler – 問題27

オイラーは特徴的な2次方程式n^2+n+41を発表した。

この方程式はnが0から39の連続した値について40個の素数を生成する。しかし、 n=40のとき、40^2+40+41 = 40(40 + 1) + 41は41で割り切れる。そしてn=41の とき、41^2+41+41は明らかに41で割り切れる。

コンピュータを使うことで驚くべき方程式n^2-79n+1601が発見された。この方 程式はnが0から79の連続した値について80個の素数を生成する。係数-79と 1601の積は-126479である。

次の形式の2次方程式を考える。n^2+an+b, |a| < 1000かつ|b| < 1000 nが0から始まる連続した値のときに最大の個数の素数を生成する2次方程式の係 数aとbの積を求めよ。

リストの内包表記を用いて全てのパターンを求め、その中で最大のものを求め る方針とする。求める値はabで比較する値は素数が連続する数なので、その tupleのリストを生成する。まず素数かどうかの判定は問題10で使用した素数の 無限リストの中のnより小さい部分の中にnが含まれるかどうかで判定する。素 数が連続する数は再帰的にnに0から順に値を計算して求める。

aとbの組み合わせは全部で400万通りであるが、n=0の時に式の値が素数になる のでbは少なくとも素数である。bが2の場合n=2で式の値が偶数になるので、bは 奇数であると仮定すると、n=1が素数になるためには少なくともaは奇数である。 以上の条件より計算を若干高速化すると以下のようなプログラムになる。

isPrime n = elem n $ takeWhile (<= n) primes

euler027 = fst $ maximumBy cmpSnd
           [(a * b, consecs a b 0) | a <-  [-999, -997..999], b <- bs]
    where bs = takeWhile (<= 999) primes
          consecs a b n
              | isPrime (n * n + a * n + b) = consecs a b (n + 1)
              | otherwise                   = n