我在玩项目欧拉问题37。问题说明如下:
数字 3797 有一个有趣的特性。作为素数本身,可以从左到右连续删除数字,并在每个阶段保持素数:3797、797、97 和 7。类似地,我们可以从右到左工作:3797、379、37 和 3。
求从左到右和从右到左都可截断的仅有的 11 个素数之和。
注意:2、3、5 和 7 不被视为可截断的素数。
这是我的代码:
import Data.Char
prime n
| n < 2 = False
| n == 2 = True
| length [x | x <- [2..(floor . sqrt $ fromIntegral n)], n `mod` x == 0] == 0 = True
| otherwise = False
truncateList xs = take (length xs) $ iterate init xs
truncateSteps n = truncateList nn ++ truncateList rn
where
nn = map digitToInt $ show n
rn = reverse nn
truncatablePrime n = and $ map (\ns -> prime $ foldl (\x y -> 10 * x + y) 0 ns) $ truncateSteps n
main = print $ sum $ take 11 $ [n | n <- [9,11..], notElem 5 $ map digitToInt $ show n, truncatablePrime n]
我相信如果我的代码完成,它会产生正确的结果。简直太慢了。我已经优化了一些东西,比如不计算包含数字“5”的数字,只检查“素数”直到数字的平方根,但这还不够。
我想对我可以研究的其他优化提供一些提示。现在,请记住,我是 haskell 的新朋友,但请提出您认为值得一提的任何建议。
更新 这是完成的解决方案,在我的机器上运行大约 1 秒:https ://gist.github.com/4250615
感谢所有优化指针!