I am not really satisfied with my F# solution to this problem because I can\'t find a beautiful & fast solution, but that\'s not the issue here. The issue is, I translated t
Your F# version isn't slow at all; it takes 0.44 seconds in F# Interactive on my machine. I don't know how you could observe such a slowness (30.5 seconds). If you compile and run the code, make sure that you're in Release mode and turning on optimization and tail call elimination.
However, you still can optimize further by eliminating the use of redundant intermediate collections.
A. Change (redundant) list [2..limit]
to range expression 2..limit
in divisorsSum
:
for i in 2..limit do
if n%i=0 then sum <- sum+i+n/i
B. Generate array of abundants without creating the big list (more faithful to C# version):
let abundants =
let arr = ResizeArray(28123)
for i in 1..28123 do
if isAbundant i then arr.Add i
arr.ToArray()
C. Calculate solve
without creating the big list:
let solve =
loopUntil 0 0
let mutable sum = 0
for i in 1..28123 do
if not <| domain.Get(i) then
sum <- sum + i
sum
The new F# version is 4x faster than the original one; it takes about 0.1 seconds to complete.
UPDATE:
Your measurement is inaccurate. First, you measured time difference between two calls of printing values. Second, EulerXXX.solve
are values; so they are pre-calculated when you compiled your program. You should declare EulerXXX.solve
as functions:
let solve() = ...
and measure execution time of function calls:
let time fn =
let sw = new System.Diagnostics.Stopwatch()
sw.Start()
let f = fn()
sw.Stop()
printfn "Time taken: %.2f s" <| (float sw.ElapsedMilliseconds)/1000.0
f
let s023 = time Euler023.solve
printf "Euler023 solution: %A" s023