简体   繁体   中英

Why my haskell program is too slow?

I tried to solve Problem 443 on ProjectEuler, https://projecteuler.net/problem=443 .

To find pattern of g, I simply implemented g in Haskell as

g::Int->Int
g 4=13
g n=g (n-1)+n `gcd` g(n-1)

But computing list t=[gi|i<-[4..100]] takes much more than 1 second. Why this happens? Even without memoization, it takes only O(n) for each g(n).

Edit: when I tried this code in ideone, it's fine, but in my computer it's not. Is that haskell version problem? I'm using version ghc 7.8.3 on Windows, while ideone using ghc 7.6.

it takes only O(n) for each g(n)

Not exactly. In your recursive case

 gn=g (n-1)+n `gcd` g(n-1) 

you are calling g twice . Which means you are getting exponential runtime actually ( O(2 n ) ).

To make sure that g (n-1) is evaluated only once in each step, use a let or where statement so that you can refer to a single value - the result of the one call - twice.

g :: Int -> Int
g 4 = 13
g n = let r = g (n-1)
      in r + n `gcd` r

when I tried this code in ideone, it's fine, but in my computer it's not. Is that haskell version problem?

Possibly, although rather an optimisation level parameter problem. Haskell's compiler can optimise functions such as yours when it detects that an expression (like g (n-1) ) appears twice, but searching for these is costly and needs to be enabled.

If you change the definition of g to:

g::Int->Int
g 4=13
g n=x+n `gcd` x
  where x = g (n-1)

then I get acceptable run times even under ghci or runhaskell (as opposed to ghc -O2 .)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM