Sucesiones de raíces digitales
La raíz digital de un número entero positivo n es el dígito resulta al sumar sus dígitos, volviendo a sumar reiteradamente resultados de esa suma y de las siguientes hasta que la suma sea un número de un dígito, al que se llama la raíz digital del número n y se representa pod D(n). Por ejemplo, la raíz digital del número 23451 es 6, porque 2+3+4+5+1 = 15 y sumando los dígitos del 15 resulta 6.
La sucesión de las raices digitales definida por un número a es la sucesión a(n) tal que a(0) = a y a(n+1) es la suma de a(n) y la raíz dígital de a(n). Por ejemplo, los primeros términos de la sucesión de las raíces digitales definida por 1 son
1 |
1,2,4,8,16,23,28,29,31,35,43,50,55,56,58,62,70,77,82,83,85,89,... |
Se observa que el menor número que no pertenece a la sucesión anterior es 3. Los primeros términos de la sucesión de las raíces digitales definida por 3 son
1 |
3,6,12,15,21,24,30,33,39,42,48,51,57,60,66,69,75,78,84,87,93,96,... |
Se observa que el menor número que no pertenece a las 2 sucesiones anteriores es 5. Los primeros términos de la sucesión de las raíces digitales definida por 5 son
1 |
5,10,11,13,17,25,32,37,38,40,44,52,59,64,65,67,71,79,86,91,92,94,... |
Definir la función
1 |
sucesionSucesionesRaicesDigitales :: [[Integer]] |
tal que sus elementos son las sucesiones de raíces digitales tal el primer elemento de cada sucesión es el menor elemento que no pertenece a las sucesiones anteriores. Por ejemplo,
1 2 |
λ> map (take 5) (take 4 sucesionSucesionesRaicesDigitales) [[1,2,4,8,16],[3,6,12,15,21],[5,10,11,13,17],[7,14,19,20,22]] |
Comprobar con QuickCheck que sucesionSucesionesRaicesDigitales tiene exactamente 5 elementos.
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
import Test.QuickCheck -- 1ª solución -- =========== sucesionSucesionesRaicesDigitales :: [[Integer]] sucesionSucesionesRaicesDigitales = map aux [1..] where aux 1 = sucesionRaicesDigitales 1 aux n = sucesionRaicesDigitales m where m = head [a | a <- [1..], all (a `noPertenece`) [aux k | k <- [1..n-1]]] -- (sucesionRaicesDigitales a) es la sucesión de las raíces digitales -- definida por un número a. Por ejemplo, -- λ> take 22 (sucesionRaicesDigitales 1) -- [1,2,4,8,16,23,28,29,31,35,43,50,55,56,58,62,70,77,82,83,85,89] -- λ> take 22 (sucesionRaicesDigitales 3) -- [3,6,12,15,21,24,30,33,39,42,48,51,57,60,66,69,75,78,84,87,93,96] -- λ> take 22 (sucesionRaicesDigitales 5) -- [5,10,11,13,17,25,32,37,38,40,44,52,59,64,65,67,71,79,86,91,92,94] -- λ> take 22 (sucesionRaicesDigitales 7) -- [7,14,19,20,22,26,34,41,46,47,49,53,61,68,73,74,76,80,88,95,100,101] -- λ> take 22 (sucesionRaicesDigitales 9) -- [9,18,27,36,45,54,63,72,81,90,99,108,117,126,135,144,153,162,171,180,189,198] sucesionRaicesDigitales :: Integer -> [Integer] sucesionRaicesDigitales a = iterate siguienteRaizDigital a -- (siguienteRaizDigital a) es el siguiente de a en la sucesión de raices -- digitales. Por ejemplo, -- siguienteRaizDigital 23 == 28 siguienteRaizDigital :: Integer -> Integer siguienteRaizDigital a = a + raizDigital a -- (raizDigital n) es la raíz digital de n. Por ejemplo, -- raizDigital 23451 == 6 raizDigital :: Integer -> Integer raizDigital n = 1 + (n-1) `mod` 9 -- (noPertenece x ys) se verifica si x no pertenece a la lista infinita -- ordenada creciente ys. Por ejemplo, -- noPertenece 2 [1,3..] == True -- noPertenece 5 [1,3..] == False noPertenece :: Integer -> [Integer] -> Bool noPertenece x ys = not (x `pertenece` ys) -- (Pertenece x ys) se verifica si x pertenece a la lista infinita -- ordenada creciente ys. Por ejemplo, -- pertenece 5 [1,3..] == True -- pertenece 2 [1,3..] == False pertenece :: Integer -> [Integer] -> Bool pertenece x ys = x == head (dropWhile (<x) ys) -- 2ª solución -- =========== sucesionSucesionesRaicesDigitales2 :: [[Integer]] sucesionSucesionesRaicesDigitales2 = aux [1..] where aux xs = sucesion xs : aux (diferencia xs (sucesion xs)) sucesion xs = sucesionRaicesDigitales (head xs) -- (diferencia xs ys) es la diferencia las listas infinitas ordenadas -- crecientes xs e ys. Por ejemplo, -- λ> take 8 (diferencia [1..] [2,4..]) -- [1,3,5,7,9,11,13,15] diferencia :: [Integer] -> [Integer] -> [Integer] diferencia (x:xs) (y:ys) | x == y = diferencia xs ys | otherwise = x : diferencia xs (y:ys) -- Propiedad -- ========= -- Del cálculo -- λ> map (take 4) (take 5 sucesionSucesionesRaicesDigitales) -- [[1,2,4,8],[3,6,12,15],[5,10,11,13],[7,14,19,20],[9,18,27,36]] -- se deduce que tiene al menos 5. Sólo queda por comprobar que no tiene más; es decir prop_sucesionSucesionesRaicesDigitales :: Integer -> Property prop_sucesionSucesionesRaicesDigitales n = n > 0 ==> any (n `pertenece`) xss where xss = take 5 (sucesionSucesionesRaicesDigitales2) -- La comprobación es -- λ> quickCheck prop_sucesionSucesionesRaicesDigitales -- +++ OK, passed 100 tests. |
Nuevas soluciones
- En los comentarios se pueden escribir nuevas soluciones.
- El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>