プロジェクトオイラーの問題27F#
-
06-09-2019 - |
質問
っていうのう 問題27 プロジェクトオイラーが、このようstumpingました。まず、コードはあまりにも長い行(aカップルの分かり、私の機械よりも重要なのは、その間違った答えが思いのスポットは何かのアルゴリズムなど、見所がたくさんありが通っている。
ここには現在の私のコードソリューションとなります。
/// Checks number for primality.
let is_prime n =
[|1 .. 2 .. sqrt_int n|] |> Array.for_all (fun x -> n % x <> 0)
/// Memoizes a function.
let memoize f =
let cache = Dictionary<_, _>()
fun x ->
let found, res = cache.TryGetValue(x)
if found then
res
else
let res = f x
cache.[x] <- res
res
/// Problem 27
/// Find a quadratic formula that produces the maximum number of primes for consecutive values of n.
let problem27 n =
let is_prime_mem = memoize is_prime
let range = [|-(n - 1) .. n - 1|]
let natural_nums = Seq.init_infinite (fun i -> i)
range |> Array.map (fun a -> (range |> Array.map (fun b ->
let formula n = n * n + a * n + b
let num_conseq_primes = natural_nums |> Seq.map (fun n -> (n, formula n))
|> Seq.find (fun (n, f) -> not (is_prime_mem f)) |> fst
(a * b, num_conseq_primes)) |> Array.max_by snd)) |> Array.max_by snd |> fst
printn_any (problem27 1000)
他のどんなコーディネートには、取得しこのアルゴリズムを実際に返右に回答しようとして少なくともし可能なアプローチ)およびb)の性能向上のために、明確に上回る"分配"のプロジェクトオイラーページをご覧ください。私は少し留守にプログラミング、アドバイスはその性を高めることが考えられますが、問題はより機能性溶液の心もます。
解決
両備考:
きのこ
b
必ず盛り.しかしながらこの問題を尋ねて最も長い列を深めn = 0, 1, 2, ...
なので、formula(0)
必ず盛りがformula(0) = b
, こ億き盛りです。私はF#プログラマが そのためのコードではなくn=0で.そのためにはもちろん、満たさない問題の必要条件
n
けの開始から0
, るが詳細は不明であ手からの正しい答えすることもできるようになる.
他のヒント
右は、すべてのヘルパー関数がどのような彼らが必要やっていたことを確認し、多くの後、私は最終的に作業(と合理的に効率的な)解決策に到達しました。
まず、のis_prime の機能(私はそれを見て作るためDimitre Novatchevのおかげで)完全に間違っていました。私は元の質問に投稿された機能に到着した、非常にかどうかはわかりませんが、私は、以前の問題で、それを使用したいので、それが働いていたと想定していました。 (ほとんどの場合、私はちょうどそれを微調整していたし、以来、それを破壊した。)とにかく、(決定的2未満のすべての整数についてfalseを返す)この機能の作業バージョンはこれです:
/// Checks number for primality.
let is_prime n =
if n < 2 then false
else [|2 .. sqrt_int n|] |> Array.for_all (fun x -> n % x <> 0)
主な機能は以下のように変更してます:
/// Problem 27
/// Find a quadratic formula that produces the maximum number of primes for consecutive values of n.
let problem27 n =
let is_prime_mem = memoize is_prime
let set_b = primes (int64 (n - 1)) |> List.to_array |> Array.map int
let set_a = [|-(n - 1) .. n - 1|]
let set_n = Seq.init_infinite (fun i -> i)
set_b |> Array.map (fun b -> (set_a |> Array.map (fun a ->
let formula n = n * n + a * n + b
let num_conseq_primes = set_n |> Seq.find (fun n -> not (is_prime_mem (formula n)))
(a * b, num_conseq_primes))
|> Array.max_by snd)) |> Array.max_by snd |> fst
速度を上げるためにここで重要なのは、唯一の値は1〜1000の素数のセットを生成することでした。のB の(の素数の機能の私の実装を使用してエラトステネスの方法のふるいです)。私はまた、不要なSeq.mapを排除することで、このコードは、もう少し簡潔にするために管理します。
だから、私は私が今持っているソリューションではかなり満足している、もちろんそれ以上の提案はまだ歓迎されるでしょうが、(それだけで第二の下かかります)...
あなたは確率的アルゴリズムを使用して、「is_prime」機能をスピードアップすることができます。このための最も簡単なの迅速なアルゴリズムの一つは、ミラー・ラビンのアルゴリズムです。
は、あなたも奇数のみが含まれている可能性a'sの配列を作ることができるの半分あなたの計算を取り除くために、
私の超高速のpythonソリューション:P
flag = [0]*204
primes = []
def ifc(n): return flag[n>>6]&(1<<((n>>1)&31))
def isc(n): flag[n>>6]|=(1<<((n>>1)&31))
def sieve():
for i in xrange(3, 114, 2):
if ifc(i) == 0:
for j in xrange(i*i, 12996, i<<1): isc(j)
def store():
primes.append(2)
for i in xrange(3, 1000, 2):
if ifc(i) == 0: primes.append(i)
def isprime(n):
if n < 2: return 0
if n == 2: return 1
if n & 1 == 0: return 0
if ifc(n) == 0: return 1
return 0
def main():
sieve()
store()
mmax, ret = 0, 0
for b in primes:
for a in xrange(-999, 1000, 2):
n = 1
while isprime(n*n + a*n + b): n += 1
if n > mmax: mmax, ret = n, a * b
print ret
main()