[英]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秒內運行。
為了能夠找到最大列表,需要評估整個列表。
所以它將從1
到1000000
計算collatzLength
並且collatzLength
是遞歸的。 最糟糕的是,你對collatzLength
的定義甚至不是尾遞歸的。
cL
是collatzLength
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.