import Data.Char (digitToInt)
import Data.Array
import Data.Numbers.Primes (isPrime)
-- 1ª definición
-- =============
listaSumaPrimaHD1 :: [Integer]
listaSumaPrimaHD1 = filter sumaPrimaHD [1..]
-- (sumaPrimaHD n) se verifica si n es de suma prima hereditario por la
-- derecha. Por ejemplo,
-- sumaPrimaHD 7426 == True
-- sumaPrimaHD 7427 == False
sumaPrimaHD n
| n < 10 = isPrime n
| otherwise = sumaPrima n && sumaPrimaHD (n `div` 10)
-- (sumaPrima n) se verifica si n es un número de suma prima. Por
-- ejemplo,
-- sumaPrima 562 == True
-- sumaPrima 514 == False
sumaPrima :: Integer -> Bool
sumaPrima = isPrime . sum . digitos
-- (digitos n) es la lista de los dígitos de n. Por ejemplo,
-- digitos 325 == [3,2,5]
digitos :: Integer -> [Integer]
digitos = map (fromIntegral . digitToInt) . show
-- 2ª definición
-- =============
listaSumaPrimaHD2 :: [Integer]
listaSumaPrimaHD2 = map fst paresSumaPrimaHDDigitos
paresSumaPrimaHDDigitos :: [(Integer, Integer)]
paresSumaPrimaHDDigitos =
paresSumaPrimaHDDigitosAux 1 [(2,2),(3,3),(5,5),(7,7)]
paresSumaPrimaHDDigitosAux :: Integer -> [(Integer,Integer)] ->
[(Integer,Integer)]
paresSumaPrimaHDDigitosAux n ac =
ac ++ paresSumaPrimaHDDigitosAux (n+1)
(concatMap extiendeSumaPrimaHD ac)
extiendeSumaPrimaHD :: (Integer,Integer) -> [(Integer,Integer)]
extiendeSumaPrimaHD (n,s) = [(n*10+k,s+k) | k <- [0..9], isPrime (s+k)]
-- 3ª definición
-- =============
listaSumaPrimaHD3 :: [Integer]
listaSumaPrimaHD3 =
map fst (concat (iterate (concatMap extiendeSumaPrimaHD3)
[(2,2),(3,3),(5,5),(7,7)]))
extiendeSumaPrimaHD3 :: (Integer,Integer) -> [(Integer,Integer)]
extiendeSumaPrimaHD3 (n,s) = [(n*10+k,s+k) | k <- extensiones ! s]
extensiones :: Array Integer [Integer]
extensiones = array (1,1000)
[(n,[k | k <- [0..9], isPrime (n+k)]) | n <- [1..1000]]
-- Comparación de eficiencia
-- =========================
-- ghci> listaSumaPrimaHD1 !! 600
-- 34004
-- (2.47 secs, 1565301720 bytes)
-- ghci> listaSumaPrimaHD2 !! 600
-- 34004
-- (0.02 secs, 7209000 bytes)
-- ghci> listaSumaPrimaHD3 !! 600
-- 34004
-- (0.01 secs, 1579920 bytes)
--
-- ghci> listaSumaPrimaHD2 !! 2000000
-- 3800024668046
-- (45.41 secs, 29056613824 bytes)
-- ghci> listaSumaPrimaHD3 !! 2000000
-- 3800024668046
-- (4.29 secs, 973265400 bytes)