我正在解决Haskell中Project Euler的一些问题。我在里面为一个谜语编写了一个程序,它没有像我预期的那样工作。
当我在运行程序时查看任务管理器时,我看到它正在使用> ghc上有1千兆字节的RAM。我的一个朋友在Java中编写了一个具有相同含义的程序,并在7秒内成功完成。
import Data.List
opl = find vw $ map (\x-> fromDigits (x++[0,0,9]) )
$ sequence [[1],re,[2],re,[3],re,[4],re,[5],re,[6],re,[7],re,[8],re]
vw x = hh^2 == x
where hh = (round.sqrt.fromIntegral) x
re = [0..9]
fromDigits x = foldl1 (\n m->10*n+m) x
我知道这个程序会输出我想要的数量,只要有足够的RAM和时间,但必须有更好的表现方式。
答案 0 :(得分:28)
这里的主要问题是序列有空间泄漏。它的定义如下:
sequence [] = [[]]
sequence (xs:xss) = [ y:ys | y <- xs, ys <- sequence xss ]
所以问题是递归调用sequence xss
生成的列表被重用于xs
的每个元素,因此它不能在结束之前被丢弃。没有空间泄漏的版本是
myseq :: [[a]] -> [[a]]
myseq xs = go (reverse xs) []
where
go [] acc = [acc]
go (xs:xss) acc = concat [ go xss (x:acc) | x <- xs ]
PS。答案似乎是Just 1229314359627783009
编辑版本,避免使用concat:
seqlists :: [[a]] -> [[a]]
seqlists xss = go (reverse xss) [] []
where
go [] acc rest = acc : rest
go (xs:xss) acc rest = foldr (\y r -> go xss (y:acc) r) rest xs
请注意,这两个版本都会以与标准sequence
不同的顺序生成结果,因此虽然它们可以解决此问题但我们不能将其用作sequence
的专用版本。< / p>
答案 1 :(得分:3)
继Simon Marlow给出的答案之后,这里有一个序列版本可以避免空间泄漏,而原本就像原版一样工作,包括保留顺序。
它仍然使用原始序列的漂亮,简单的列表理解 - 唯一的区别是引入了伪数据依赖,阻止递归调用被共享。
sequenceDummy d [] = d `seq` [[]]
sequenceDummy _ (xs:xss) = [ y:ys | y <- xs, ys <- sequenceDummy (Just y) xss ]
sequenceUnshared = sequenceDummy Nothing
我认为这是一种避免共享导致空间泄漏的更好方法。
我责怪过度分享“完全懒惰”的转变。通常,这可以很好地创建共享以避免重新计算,但有时重新计算比存储共享结果更有效。
如果有更直接的方法告诉编译器不要共享特定的表达式,那就太好了 - 上面的虚拟Maybe
参数有效并且有效,但它基本上是一个复杂到足够复杂的黑客ghc不能说没有真正的依赖。 (在严格的语言中,您没有这些问题,因为您只有将变量显式绑定到值的共享。)
答案 2 :(得分:0)
您的问题似乎是一个旧的GHC错误(我认为已经修复)与Integer导致空间泄漏。使用-O2编译时,下面的代码在大约150毫秒内完成。
import Data.List
import Data.Word
main = print opl
opl :: Maybe Word32
opl = find vw $ map (\x-> fromDigits (x++[0,0,9]) ) $ sequence [[1],re,[2],re,[3],re,[4],re,[5],re,[6],re,[7],re,[8],re]
vw x = hh^2 == x
where hh = (round.sqrt.fromIntegral) x
re = [0..9]
fromDigits x = foldl1 (\n m->10*n+m) x
答案 3 :(得分:-2)
由于你正在寻找一个带有vw中找到的那些特征的十九位数字,我会尝试简化映射函数中的构造,只为启动者说fromDigits x*1000+9
。附加到列表是O(左侧列表的长度),因此最后抛出最后三位数会损害计算时间。
除此之外(对你们两个人来说),使用严格版本的折叠(foldl1'
)也会有所帮助。