【发布时间】:2019-05-14 13:46:56
【问题描述】:
我写了一段 Haskell 代码来计算 Collatz chain 的长度。给定一个数 n,如果 n 是偶数,则序列中的下一个数是 n/2;如果 n 是奇数,则为 3*n+1。序列在收敛到 1 时结束。我想从某个输入数字以下的任何数字开始计算最长链的长度。
我尝试使用记忆函数来实现长度计算,因为我预计需要从一些数字开始的链长度。因此,从 726 开始的链的长度将只是 1 + 从 363 开始的链的长度,这已经计算过了。我的代码如下所示。
collatz :: Int -> Int
collatz n
| even n = n `div` 2
| otherwise = 3 * n + 1
collatzLength :: Int -> Int
collatzLength = (fmap len [0 ..] !!)
where len 0 = 0
len 1 = 1
len n = 1 + (collatzLength . collatz $ n)
maxLengthBelow :: Int -> Int
maxLengthBelow = foldl1 max . fmap collatzLength . enumFromTo 1
main :: IO()
main = print $ maxLengthBelow 10000
此代码有效,但占用大量内存。在分析它时,输入 10000 运行 main,len 只被调用了 21664 次,正如预期的那样,但程序需要 16 秒和 4.5Gb 的内存!是什么占用了所有的内存?我本来希望 memoized 函数能够产生快速、低内存的解决方案。
【问题讨论】:
标签: haskell