UPDATED: solution now faster.
Problem 47 says:
The first two consecutive numbers to have two distinct prime factors are:
14 = 2 × 7
15 = 3 × 5The 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()