Problem #69 says:
Euler’s Totient function, φ(n) [sometimes called the phi function], is used to determine the number of
numbers less than n which are relatively prime to n. For example, as 1, 2, 4, 5, 7, and 8, are all less than
nine and relatively prime to nine, φ(9)=6.Find the value of n ≤ 1,000,000 for which n/φ(n) is a maximum.
For this problem I created a class that held the number and it’s totient and then create them in parallel.
Then I loop through the mess looking for the instance with the highest check value. The Parallelism is handled by
the PSeq object from the F# power pack.
Solution in f# and requires .net 4 and the F# power pack from codeplex. Runs in ~48 seconds.
#light
open System
open System.Diagnostics
open Microsoft.FSharp.Linq
open Microsoft.FSharp.Collections
//set the limit and bound
let UpperLimit = 1000000.
let UpperBound = (Math.Sqrt(UpperLimit))
//generate numbers to check
let Primes = ref [2. .. (UpperLimit)] in
// loop through all numbers
// keep removing numbers that divide evenly
for div = 2 to int UpperBound do
Primes := List.filter(fun num -> (num % (float div) <> 0. || (float div) >= num))
!Primes
done;
let rec factorise (n:float) =
if n = 1. then [] else
let a = !Primes |> List.find (fun x -> n % x = 0.)
a :: factorise (n / a)
let Totient (x:float) =
(factorise x)
|> Seq.distinct
|> Seq.map (fun x -> 1. - (1./x))
|> Seq.fold(fun acc a -> acc * a) x
type TestCase (Num:float) =
let mutable _num = Num
let _tot = Totient (float _num)
member x.num
with get() = _num
and set(v) = _num <- v
member x.Check
with get() = x.num / _tot
Console.WriteLine("Starting Check")
let watch = new Stopwatch()
watch.Start()
let Answer =
let mutable Ans = new TestCase(1.)
let Tests =
[2. .. 1000000.]
|> PSeq.map (fun x -> new TestCase(x))
for t in Tests do
if t.Check > Ans.Check then
Ans <- t
Ans.num
Console.WriteLine(Answer)
watch.Stop()
Console.WriteLine(watch.Elapsed)
Console.ReadKey() |> ignore