繁体   English   中英

为什么这个Haskell表达式如此之慢?

[英]Why is this Haskell expression so slow?

我正在研究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

我正在运行以下GHCi

maximumBy maxTuple [(collatzLength x, x) | x <- [1..1000000]]

我知道如果Haskell严格评估,那么这个时间就像O(n 3 )。 由于Haskell懒惰地评估,看起来这应该是n的一些常数倍。 这已经运行了近一个小时了。 似乎很不合理。 有谁知道为什么?

您假设collatzLength函数将被记忆。 Haskell不进行自动记忆。 你需要自己做。 这是使用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]]

当使用-O2编译时,这将在大约1秒内运行。

为了能够找到最大列表,需要评估整个列表。

所以它将从11000000计算collatzLength并且collatzLength是递归的。 最糟糕的是,你对collatzLength的定义甚至不是尾递归的。

cLcollatzLength

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..]]

简单测试:

ghci> cL !! 13
10

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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