[英]Why is this Haskell expression so slow?
I'm working on Project Euler Problem 14. Here's my solution. 我正在研究Project Euler Problem 14.这是我的解决方案。
import Data.List
collatzLength :: Int->Int
collatzLength 1 = 1
collatzLength n | odd n = 1 + collatzLength (3 * n + 1)
| even n = 1 + collatzLength (n `quot` 2)
maxTuple :: (Int, Int)->(Int, Int)->Ordering
maxTuple (x1, x2) (y1, y2) | x1 > y1 = GT
| x1 < y1 = LT
| otherwise = EQ
I'm running the following out of GHCi 我正在运行以下GHCi
maximumBy maxTuple [(collatzLength x, x) | x <- [1..1000000]]
I know that if Haskell evaluated strictly, the time on this would be something like O(n 3 ). 我知道如果Haskell严格评估,那么这个时间就像O(n 3 )。 Since Haskell evaluates lazily though, it seems like this should be some constant multiple of n.
由于Haskell懒惰地评估,看起来这应该是n的一些常数倍。 This has been running for nearly an hour now.
这已经运行了近一个小时了。 Seems very unreasonable.
似乎很不合理。 Does anyone have any idea why?
有谁知道为什么?
You're assuming that the collatzLength
function will be memoized. 您假设
collatzLength
函数将被记忆。 Haskell does not do automatic memoization. Haskell不进行自动记忆。 You'll need to do that yourself.
你需要自己做。 Here's an example using the data-memocombinators package.
这是使用data-memocombinators包的示例。
import Data.List
import Data.Ord
import qualified Data.MemoCombinators as Memo
collatzLength :: Integer -> Integer
collatzLength = Memo.arrayRange (1,1000000) collatzLength'
where
collatzLength' 1 = 1
collatzLength' n | odd n = 1 + collatzLength (3 * n + 1)
| even n = 1 + collatzLength (n `quot` 2)
main = print $ foldl1' max $ [(collatzLength n, n) | n <- [1..1000000]]
This runs in about 1 second when compiled with -O2
. 当使用
-O2
编译时,这将在大约1秒内运行。
For being able to find a maximum of a list, the whole list needs to be evaluated. 为了能够找到最大列表,需要评估整个列表。
So it will calculate collatzLength
from 1
to 1000000
and collatzLength
is recursive. 所以它将从
1
到1000000
计算collatzLength
并且collatzLength
是递归的。 The worst thing is, that your definition of collatzLength
is even not tail-recursive. 最糟糕的是,你对
collatzLength
的定义甚至不是尾递归的。
cL
is short for collatzLength
cL
是collatzLength
cL!!n
stands for collatzLength n
cL!!n
代表collatzLength n
cL :: [Int]
cL = 1 : 1 : [ 1 + (if odd n then cL!!(3*n+1) else cL!!(n `div` 2)) | n <- [2..]]
Simple test: 简单测试:
ghci> cL !! 13
10
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.