Project Euler Problem #47!

February 5th, 2010
by Serinox

UPDATED: solution now faster.

Problem 47 says:

The first two consecutive numbers to have two distinct prime factors are:

14 = 2 × 7
15 = 3 × 5

The first three consecutive numbers to have three distinct prime factors are:

644 = 2² × 7 × 23
645 = 3 × 5 × 43
646 = 2 × 17 × 19.

Find the first four consecutive integers to have four distinct primes factors. What is the first of these numbers?

So I attempted to do this one in F# to help me learn the language and the basic work flow I came up with for the first attempt was to create the list of numbers to check use Seq.windowed to group them in series of 4 then to factor and check there factors against one another.

Solution below requires .net 4 and f# and runs in about 2 min.

#light
open System
open System.Diagnostics
open System.Collections.Generic

//numbers to check
let nums = [130000 .. 140000]

//get some prime factors

//set the limit and bound
let UpperLimit = 5000.
let UpperBound = 5000

//generate numbers to check
let LNums = ref [2..(int UpperLimit)] in

let DivisorTest x y =
    if (x % y =0) then
        true
    else
        false

// loop through all numbers
// keep removing numbers that divide evenly
for div = 2 to UpperBound do
  LNums := List.filter(fun num -> (num % div <> 0 || div >= num))
        !LNums
done;

let Primes:list<int> = !LNums

let rec factorise n =
    if n = 1 then [] else
    let a = [2 .. n] |> List.find (fun x -> n % x = 0)
    a :: factorise (n / a)

let union l1 l2 l3 l4 =
    l1 @ l2 @ l3 @ l4 |> Seq.distinct |> List.ofSeq

let UniqueList factors =
    let dict = new Dictionary<int,int>()
    for x in factors do
        if (dict.ContainsKey x) then
            dict.[x] <- dict.[x] + 1
        else
            dict.Add(x,1)
    let mutable t2 = []
    for x2 in dict.Keys do
        t2 <- int ((double x2) ** (double dict.[x2])) :: t2
    t2

let NonPrime = (Set.ofList nums) - (Set.ofList Primes) |> Set.toList

Console.WriteLine("Starting check")
let watch = new Stopwatch()
watch.Start()

let MList l =
    let l2:int = List.reduce (fun acc elem -> acc * elem) l
    l2

let Check (L:array<int list>) =
    let n1:list<int> = L.[0]
    let n2:list<int> = L.[1]
    let n3:list<int> = L.[2]
    let n4:list<int> = L.[3]
    if (n1.Length <> 4) || (n2.Length <> 4) || (n3.Length <> 4) || (n4.Length <> 4) then
        false
    else
        if ((MList n1)+1) <> (MList n2) then
            false
        else if ((MList n2)+1) <> (MList n3) then
            false
        else if ((MList n3)+1) <> (MList n4) then
            false
        else
            true

let CheckLength (l:list<int>) =
    if l.Length <> 4 then
        false
    else
        true

let N =
    NonPrime
    |> Seq.map factorise
    |> Seq.map UniqueList
    |> Seq.distinct
    |> Seq.filter CheckLength
    |> Seq.windowed 4
    |> Seq.filter Check
    |> Seq.take 1
    |> Seq.toArray

watch.Stop()

Console.WriteLine((MList N.[0].[0]))
Console.WriteLine(watch.Elapsed)
Console.ReadKey()

Tags: , ,
Posted in Project Euler | Comments (0)

No comments yet

Leave a Reply

You must be logged in to post a comment.
This blog collects statistical data with Statpress SEOlution in the reVierphone Edition! Give it a try.