Правильно, после тщательной проверки того, что все вспомогательные функции выполняют то, что должны, я наконец-то нашел работающее (и достаточно эффективное) решение.
Во-первых, функция is_prime была полностью неправильной (спасибо Димитру Новачеву за то, что заставил меня взглянуть на это). Я не совсем уверен, как я пришел к функции, которую я разместил в исходном вопросе, но я предполагал, что она работает, так как я использовал ее в предыдущих задачах. (Скорее всего, я только что настроил и сломал его.) В любом случае, рабочая версия этой функции (которая критически возвращает false для всех целых чисел меньше 2) такова:
/// 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 (используя функцию primes , моя реализация Sieve of Метод Эратосфена). Мне также удалось сделать этот код немного более лаконичным, исключив ненужный Seq.map.
Итак, я очень доволен решением, которое у меня есть сейчас (оно занимает чуть меньше секунды), хотя, конечно, любые дальнейшие предложения будут приветствоваться ...