Euler Problem 104
1. Solutions
There are two solutions below. One is written by me and another from haskell wiki.
They look quite similar and I can not figure out why the wiki solution can solve problem but not mine. (Actually mine take more than 15 minutes)
- My Solution
│ main = print $ snd $ head $ │ │ │dropWhile (\ (x,y) -> (not . isLastNinePandigit "123456789") x) │ │ │ │ │ (zip fibs [1..]) │ │ │ │ │ │ bothNinePandigit digits n = isFirstNinePandigit digits n │ │ │ │ │ │ │ │ && isLastNinePandigit digits n │ │ │ │ │ │ │ │ │ isLastNinePandigit digits = (== digits) . sort . lastDigits 9 │ isFirstNinePandigit digits = (== digits) . sort . firstDigits 9 │ │ firstDigits k n = take k (show n) │ lastDigits k n = show (n `mod` 10^k)
- Haskell Wiki solution1
│ │ fibs = 1 : 1 : zipWith (+) fibs (tail fibs) │ │ isFibPan n = │ let a = n `mod` 1000000000 │ │ b = sort (show a) │ │ c = sort $ take 9 $ show n │ in b == "123456789" && c == "123456789" │ │ ex_104 = snd $ head $ │ │ │ dropWhile (\(x,y) -> (not . isFibPan) x) (zip fibs [1..])
2. Why the differences?
The key point here is should test start nine digits first or test end nine digits.
Two concerns here:
show
function is (relatively) slow which used in test first 9 digits function.- quite few numbers are end in digits 1..9 in the first 329000 numbers
Therefore test last 9 digits first make great performance improvement.
Thanks Brent2 explanation this sneaky thing very comprehensively in haskell-beginner.
3. Profiling
What help to identify is the GHC profiling tool.
Several options used here are
- prof: for basic time and allocation profiling
- auto-all: auto insert cost centers on all top level functions. “cost center” is a location in the program like to collect statistics about and GHC will generate code to compute the cost of evalutating the expression at each location. e.g.
│ mean s = {-# SCC "mean" #-} sum s / fromIntegral (length s)
- caf-all: function with no parameters only computed once. CAF means constant applicative forms which used for calculate that once time evaluation.
- fforce-recomp: force full recompilation.
More details could go to chapter 253 of [Real World Haskell] and GHC user guider chapter 54.
│ # build with prof option on │ ghc --make -O2 -prof -auto-all -rtsopts p104.hs │ │ # then run │ ./p104 +RTS -p -RTS
4. Further
- Chapter 25 in Real Work Haskell about profile