Números cubifinitos
El enunciado del problema Números cubifinitos de ¡Acepta el reto! es el siguiente
Se dice que un número es cubifinito cuando al elevar todos sus dígitos al cubo y sumarlos el resultado o bien es 1 o bien es un número cubifinito.
Por ejemplo, el número 1243 es cubifinito, pues al elevar todos sus dígitos al cubo obtenemos 100 que es cubifinito.
Por su parte, el 513 no es cubifinito, pues al elevar al cubo sus dígitos conseguimos el 153 que nunca podrá ser cubifinito, pues la suma de los cubos de sus dígitos vuelve a dar 153.
Definir las funciones
1 2 |
esCubifinito :: Int -> Bool grafica :: Int -> IO () |
tales que
- (esCubifinito n) se verifica si n es un número cubifinito. Por ejemplo,
1 2 3 4 5 |
esCubifinito 1 == True esCubifinito 10 == True esCubifinito 1243 == True esCubifinito 87418 == True esCubifinito 513 == False |
- (grafica n) dibuja la gráfica de la sucesión de los primeros n números cubifinitos. Por ejemplo, al evaluar (grafica 50) se dibuja
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import Graphics.Gnuplot.Simple -- 1ª solución -- =========== esCubifinito :: Int -> Bool esCubifinito n = aux [n] where aux (n:ns) | n == 1 = True | n `elem` ns = False | otherwise = aux (sumaCubosDigitos n : n : ns) -- (sumaCubosDigitos b) es la suma de los cubos de los dígitos de n. Por -- ejemplo, -- sumaCubosDigitos 513 == 153 sumaCubosDigitos :: Int -> Int sumaCubosDigitos = sum . map (^3) . digitos -- (digitos n) es la lista de los dígitos de n. Por ejemplo, -- digitos 513 == [5,1,3] digitos :: Int -> [Int] digitos n = [read [c] | c <- show n] -- 2ª solución -- =========== esCubifinito2 :: Int -> Bool esCubifinito2 n = primerRepetido (orbita n) == 1 -- (orbita n) es la lista cuyo primer elemento es n y los siguientes se -- obtienen sumando los cubos de los digitos del elemento anterior. Por -- ejemplo, -- take 9 (orbita 2) == [2,8,512,134,92,737,713,371,371] orbita :: Int -> [Int] orbita n = iterate sumaCubosDigitos n -- (primerRepetido xs) es el primer elemento repetido de la lista -- xs. Por ejemplo, -- primerRepetido [3,7,5,7,2] == 7 primerRepetido :: Eq a => [a] -> a primerRepetido xs = aux xs [] where aux (x:xs') ys | x `elem` ys = x | otherwise = aux xs' (x:ys) grafica :: Int -> IO () grafica n = plotList [Key Nothing, PNG "Numeros_cubifinitos.png"] (zip [1..n] [x | x <- [1..], esCubifinito x]) |
La definición es incorrecta. Para n = 4, no llega a ninguna solución.
la definición anterior es incorrecta. No contempla la posibilidad de que se generen bucles de más de un número de longitud
Podemos generar en unos pocos segundos una gráfica con el primer millón de cubifinitos.
Si no nos parece suficiente 1 millón, podemos reducir de O(log10 n) a O(1) sin importar ya el número de dígitos; pudiendo calcular (por ejemplo) casi 2 millones en unos 15 segundos (y graficarlos).