【发布时间】:2015-12-25 04:21:22
【问题描述】:
我正在使用 Project Euler 来学习 Haskell。我是 Haskell 的新手,想出一个不需要花费大量时间的算法时遇到了很多麻烦。我估计这里的程序需要 14 千兆年才能得出解决方案。
问题:
100 万以下的哪个素数可以写成最 连续素数?
这是我的来源。我遗漏了 isPrime。我已经发布了它,因为它解决问题的效率太低了。我认为问题在于 slicedChains 和 primeChains 调用,但我不确定它是什么。我以前用 C++ 解决过这个问题。但无论出于何种原因,Haskell 中的有效解决方案似乎超出了我的范围。
编辑:我已经包含了 isPrime。
import System.Environment (getArgs)
import Data.List (nub,maximumBy)
import Data.Ord (comparing)
isPrime :: Integer -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime x
| any (== 0) (fmap (x `mod`) [2..x-1]) = False
| otherwise = True
primeChain :: Integer -> [Integer]
primeChain x = [ n | n <- 1 : 2 : [3,5..x-1], isPrime n ]
slice :: [a] -> [Int] -> [a]
slice xs args = take (to - from + 1) (drop from xs)
where from = head args
to = last args
subsequencesOfSize :: Int -> [a] -> [[a]]
subsequencesOfSize n xs = let l = length xs
in if n>l then [] else subsequencesBySize xs !! (l-n)
where
subsequencesBySize [] = [[[]]]
subsequencesBySize (x:xs) = let next = subsequencesBySize xs
in zipWith (++) ([]:next) (map (map (x:)) next ++ [[]])
slicedChains :: Int -> [Integer] -> [[Integer]]
slicedChains len xs = nub [x | x <- fmap (xs `slice`) subseqs, length x > 1]
where subseqs = [x | x <- (subsequencesOfSize 2 [1..len]), (last x) > (head x)]
primeSums :: Integer -> [[Integer]]
primeSums x = filter (\ns -> sum ns == x) chain
where xs = primeChain x
len = length xs
chain = slicedChains len xs
compLength :: [[a]] -> [a]
compLength xs = maximumBy (comparing length) xs
cleanSums :: [Integer] -> [[Integer]]
cleanSums xs = fmap (compLength) filtered
where filtered = filter (not . null) (fmap primeSums xs)
main :: IO()
main = do
args <- getArgs
let arg = read (head args) :: Integer
let xs = primeChain arg
print $ maximumBy (comparing length) $ cleanSums xs
【问题讨论】:
-
您是否尝试过在较小的输入大小(例如低于 1000 的素数)上进行分析并查看哪个函数花费的时间最多?
-
是的,它看起来像是 slicedChain 并且可能是 primeChain 的双重调用。我只是不完全确定如何避免它们。
-
你可能想用一个筛子来制作一个包含所有素数的向量(甚至是一个列表),直到一百万,然后你可能想把它们塞进一个
IntSet。素数向量可以让你很容易地总结连续的,而IntSet可以很容易地检查一个数字是否是素数。 -
不理想的
isPrime很容易成为罪魁祸首。为什么要把它排除在外?它不应该。 -
我已经包含了我的 isPrime 函数。如果我计算正确,它似乎在线性时间内运行。