sumas2Capicuas :: Integer -> [(Integer, Integer)]
sumas2Capicuas x =
[(y,z) | y <- takeWhile (<= (x `div` 2)) capicuas
, let z = x - y
, esCapicua z]
-- capicuas es la sucesión de los números capicúas. Por ejemplo,
-- λ> take 45 capicuas
-- [0,1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,101,111,121,131,
-- 141,151,161,171,181,191,202,212,222,232,242,252,262,272,282,292,
-- 303,313,323,333,343,353]
-- Se usará la 2ª definición del ejercicio "Sucesión de capicúas".
capicuas :: [Integer]
capicuas = capicuasImpares `mezcla` capicuasPares
-- capicuasPares es la sucesión del cero y las capicúas con un número
-- par de dígitos. Por ejemplo,
-- λ> take 17 capicuasPares
-- [0,11,22,33,44,55,66,77,88,99,1001,1111,1221,1331,1441,1551,1661]
capicuasPares :: [Integer]
capicuasPares =
[read (ns ++ reverse ns) | n <- [0..]
, let ns = show n]
-- capicuasImpares es la sucesión de las capicúas con un número
-- impar de dígitos a partir de 1. Por ejemplo,
-- λ> take 20 capicuasImpares
-- [1,2,3,4,5,6,7,8,9,101,111,121,131,141,151,161,171,181,191,202]
capicuasImpares :: [Integer]
capicuasImpares =
[1..9] ++ [read (ns ++ [z] ++ reverse ns)
| n <- [1..]
, let ns = show n
, z <- "0123456789"]
-- (mezcla xs ys) es la lista ordenada obtenida mezclando las dos listas
-- ordenadas xs e ys, suponiendo que ambas son infinitas y con elementos
-- distintos. Por ejemplo,
-- take 10 (mezcla [2,12..] [5,15..]) == [2,5,12,15,22,25,32,35,42,45]
-- take 10 (mezcla [2,22..] [5,15..]) == [2,5,15,22,25,35,42,45,55,62]
mezcla :: Ord a => [a] -> [a] -> [a]
mezcla us@(x:xs) vs@(y:ys)
| x < y = x : mezcla xs vs
| otherwise = y : mezcla us ys
-- (esCapicua x) se verifica si x es capicúa. Por ejemplo,
-- esCapicua 353 == True
-- esCapicua 3553 == True
-- esCapicua 3535 == False
esCapicua :: Integer -> Bool
esCapicua x =
xs == reverse xs
where xs = show x
noSuma2Capicuas :: [Integer]
noSuma2Capicuas =
[x | x <- [0..]
, null (sumas2Capicuas x)] |
Se puede definir “show x” como una variable local en la función “esCapicua” para mejorar la eficiencia de esta.