After publishing the performance stats of my previous solution to Project Euler #4, I got thinking about how I might improve things. I didn’t want to be overly anal with regards to things such as memory allocations, because it’s easy to get stuck in the perpetual loop of attempted optimisations. Instead I wanted to think of a method that wasn’t as brute force as the previous one. If you’re interested to see what I did, read on (Note: This is a spoiler for the problem, just like the last post was).
Let’s start by looking at the source, which I commented heavily:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
If that’s not clear, then drop me a comment and I’ll try and explain further. In a nutshell, using the properties we know of the target result, we can narrow down the set of values that we can use to test.
Proof is in the perf! Check out the stats:
Sat Mar 22 13:43 2008 Time and Allocation Profiling Report (Final)
main +RTS -p -RTS
total time = 2.36 secs (118 ticks @ 20 ms)
total alloc = 327,270,176 bytes (excludes profiling overheads)
COST CENTRE MODULE %time %alloc
CAF Main 100.0 100.0
individual inherited
COST CENTRE MODULE no. entries %time %alloc %time %alloc
MAIN MAIN 1 0 0.0 0.0 100.0 100.0
CAF Main 152 17 100.0 100.0 100.0 100.0
CAF Text.Read.Lex 129 8 0.0 0.0 0.0 0.0
CAF GHC.Real 127 1 0.0 0.0 0.0 0.0
CAF GHC.Read 124 1 0.0 0.0 0.0 0.0
CAF GHC.Float 123 9 0.0 0.0 0.0 0.0
CAF GHC.Handle 88 4 0.0 0.0 0.0 0.0
So the total time dropped to 2.26 seconds. Quite an improvement over the previous implementation (around 4x faster).
Thoughts on further improvements?