【发布时间】:2012-12-12 22:21:04
【问题描述】:
我一直在做项目欧拉问题来学习 Haskell。
我在路上遇到了一些障碍,但设法解决了第 14 题。 问题是,小于 1 000 000 的起始数字会产生最长的 Collatz 链(链开始后数字允许超过 100 万)。
我尝试了几种解决方案,但都没有奏效。 我想做一个反转。从 1 开始,当数量超过 100 万时终止,但这显然行不通,因为条款可能会超过 100 万。
我尝试过记忆普通算法,但同样,数字太大,无法记忆。
我读到最明显的解决方案应该可以解决这个问题,但由于某种原因,我的解决方案需要 10 多秒才能达到 20 000 的最大值。更不用说 100 万了。
这是我目前正在使用的代码:
reg_collatz 1 = 1
reg_collatz n
| even n = 1 + reg_collatz (n `div` 2)
| otherwise = 1 + reg_collatz (n * 3 + 1)
solution = foldl1 (\a n -> max a (reg_collatz n)) [1..20000]
非常欢迎任何帮助。
【问题讨论】:
-
通常的第一步是
foldl1->foldl1',使用quotRem代替even和div,如果可能,专门针对Int,并添加备忘录。不过,我觉得我们之前已经回答过这个问题几次了,所以在充实这个答案之前先搜索一个副本...... -
你不会从
ghci(解释器)运行它,是吗?因为当使用ghc -O2编译时,您的代码在我的机器上输出 20000 的 0.14 秒和 1000000 的 10 秒的答案。它可能仍然可以优化,但只是为了确保我们从一开始就做对了。 -
切换到
Int(在64位GHC上),用quot代替div,用ghc -O2 -fllvm编译,这里不到1秒。但是请注意,您不需要最长链的长度,而是需要起始编号。