Project Euler — Problem 27 Solution

Problem

Euler pub­lished the remark­able qua­drat­ic for­mu­la:

n² + n + 41

It turns out that the for­mu­la will pro­duce 40 primes for the con­sec­u­tive val­ues n = 0 to 39. How­ev­er, when n = 40, 402 + 40 + 41 = 40(40 + 1) + 41 is divis­i­ble by 41, and cer­tain­ly when n = 41, 41² + 41 + 41 is clear­ly divis­i­ble by 41.

Using com­put­ers, the incred­i­ble for­mu­la  n² — 79n + 1601 was dis­cov­ered, which pro­duces 80 primes for the con­sec­u­tive val­ues n = 0 to 79. The prod­uct of the coef­fi­cients, -79 and 1601, is -126479.

Con­sid­er­ing qua­drat­ics of the form:

n² + an + b, where |a| < 1000 and |b| < 1000

where |n| is the modulus/absolute val­ue of n

e.g. |11| = 11 and |-4| = 4

Find the prod­uct of the coef­fi­cients, a and b, for the qua­drat­ic expres­sion that pro­duces the max­i­mum num­ber of primes for con­sec­u­tive val­ues of n, start­ing with n = 0.

Solution

let hasDivisor(n) =
    let upperBound = int64(sqrt(double(n)))
    [2L..upperBound] |> Seq.exists (fun x -> n % x = 0L)

// need to consider negative values
let isPrime(n) = if n <= 1L then false else not(hasDivisor(n))

// the quadratic expression
let F (n:int64) (a:int64) (b:int64) = (n*n) + (a*n) + b

// function to return the number of consecutive primes the coefficients generate
let primeCount a b =
    Seq.unfold (fun state -> Some(state, state + 1L)) 0L
    |> Seq.takeWhile (fun n -> isPrime (F n a b))
    |> Seq.length

let aList, bList = [-999L..999L], [2L..999L] |> List.filter isPrime

let answer =
    let (a, b, _) =
        aList
        |> List.collect (fun a ->
            bList
            |> List.filter (fun b -> a + b >= 1L)
            |> List.map (fun b -> (a, b, primeCount a b)))
        |> List.maxBy (fun (_, _, count) -> count)
    a * b

Whilst I start­ed off using a brute force approach (which took quite a while to run) I realised that most of the com­bi­na­tions of a and b don’t gen­er­ate any primes at all. In order to reduce the num­ber of com­bi­na­tions you need to check, con­sid­er the cas­es when n = 0 and n = 1:

n = 0: expres­sion eval­u­ates to b, in order for this to gen­er­ate a prime b must be >= 2.

n = 1: expres­sion eval­u­ates to 1 + a + b, in order for this to gen­er­ate a prime 1 + a + b must be >= 2, there­fore a + b >= 1.