Por 3 o más 5
El enunciado del problema Por 3 o más 5 de ¡Acepta el reto! es el siguiente
Cuenta la leyenda que un famoso matemático, tras aprender a sumar y multiplicar a la tierna edad de 3 años en apenas 5 días, se dio cuenta de que, empezando por 1, podía generar un montón de números sin más que multiplicar por 3 o sumar 5 a alguno de los que ya hubiera generado antes.
Por ejemplo, el 23 (edad a la que se casaría) lo obtuvo así: ((1 + 5) × 3) + 5
Por su parte el 77 (edad a la que tendría su primer bisnieto) lo consiguió: (((1 × 3 + 5) × 3) × 3) + 5Por mucho que lo intentó, algunos números, sin embargo, resultaron ser imposibles de obtener, como por ejemplo el 5, el 7 o el 15.
Se dice que un número es generable si se puede escribir como una sucesión (quizá vacía) de multiplicaciones por 3 y sumas de 5 al número 1.
Definir las siguientes funciones
1 2 3 |
generables :: [Integer] generable :: Integer -> Bool arbolGenerable :: Integer -> Tree Integer |
tales que
- generables es la sucesión de los números generables. Por ejemplo,
1 2 3 4 |
λ> take 20 generables [1,3,6,8,9,11,13,14,16,18,19,21,23,24,26,27,28,29,31,32] λ> generables !! (10^6) 1250008 |
- (generable x) se verifica si x es generable. Por ejemplo,
1 2 3 4 5 |
generable 23 == True generable 77 == True generable 15 == False generable 1250008 == True generable 1250010 == False |
- (arbolGenerable x) es el árbol de los números generables menores o iguales a x. Por ejemplo,
1 2 3 4 5 6 7 8 9 10 11 12 |
λ> putStrLn (drawTree (fmap show (arbolGenerable 11))) 1 | +- 3 | | | +- 9 | | | `- 8 | `- 6 | `- 11 |
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 |
import Graphics.Gnuplot.Simple generables :: [Integer] generables = 1 : mezcla [3 * x | x <- generables] [5 + x | x <- generables] -- (mezcla xs ys) es la lista ordenada obtenida mezclando las dos listas -- ordenadas xs e ys, suponiendo que ambas son infinitas. 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 | x == y = x : mezcla xs ys | otherwise = y : mezcla us ys generable :: Integer -> Bool generable x = x == head (dropWhile (<x) generables) -- 2ª definición generable2 :: Integer -> Bool generable2 1 = True generable2 x = (x `mod` 3 == 0 && generable2 (x `div` 3)) || (x > 5 && generable2 (x - 5)) generables2 :: [Integer] generables2 = filter generable2 [1..] arbolGenerable :: Integer -> Tree Integer arbolGenerable n = aux 1 where aux x | 3*x <= n && 5+x <= n = Node x [aux (3*x), aux (5+x)] | 3*x <= n = Node x [aux (3*x)] | 5+x <= n = Node x [aux (5+x)] | otherwise = Node x [] -- 3ª definición generable3 :: Integer -> Bool generable3 x = x `elem` arbolGenerable x |
5 Comentarios