如果你使用辅助功能,你可以这样做:
isPrime :: Integer -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime n
| (length [x | x <- [2 .. n-1], n `mod` x == 0]) > 0 = False
| otherwise = True
isSpecialPrime :: Integer -> Bool
isSpecialPrime 1 = False
isSpecialPrime x =
let firstNeighboring = findNeighbore x in
isSpecialPrime' x firstNeighboring
isSpecialPrime' :: Integer -> Integer -> Bool
isSpecialPrime' _ 0 = False
isSpecialPrime' p x =
let firstNeighboring = findNeighbore x in
let secondNeighboring = findNeighbore firstNeighboring in
if (1 + firstNeighboring + secondNeighboring) == p
then True
else isSpecialPrime' p firstNeighboring
findNeighbore 0 = 0
findNeighbore x = if isPrime (x-1) then x-1 else findNeighbore (x-1)
primes :: [Integer]
primes = sieve (2 : [3, 5..])
where
sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
举个例子:
filter isSpecialPrime $ take 40 primes
=> [13,19,31,37,43,53,61,79,101,113,139,163,173]
一点优化:
isSpecialPrime' :: Integer -> Integer -> Bool
isSpecialPrime' _ 1 = False
isSpecialPrime' p x =
let firstNeighboring = findNeighbore x in
let secondNeighboring = findNeighbore firstNeighboring in
let sumNeigh = secondNeighboring + firstNeighboring in
if (p `div` 3) > sumNeigh
then False else
if (1 + sumNeigh) == p
then True
else isSpecialPrime' p firstNeighboring
示例:
filter isSpecialPrime $ take 100 primes
=> [13,19,31,37,43,53,61,79,101,113,139,163,173,199,211,223,241,269,277,331,353,373,397,457,463,509,521,541]