Entero positivo con ciertas propiedades
El 6 de octubre, se propuso en el blog Gaussianos el siguiente problema
Demostrar que para todo entero positivo n, existe otro entero positivo que tiene las siguientes propiedades:
- Tiene exactamente n dígitos.
- Ninguno de sus dígitos es 0.
- Es divisible por la suma de sus dígitos.
Definir la función
especiales :: Integer -> [Integer]
tal que (especiales n) es la lista de los números enteros que cumplen las 3 propiedades anteriores para n. Por ejemplo,
take 3 (especiales 2) == [12,18,21] take 3 (especiales 3) == [111,112,114] head (especiales 30) == 111111111111111111111111111125 length (especiales 3) == 108 null (especiales 1000) == False
En el primer ejemplo, 12 es un número especial para 2 ya que tiene exactamente 2 dígitos, ninguno de sus dígitos es 0 y 12 es divisible por la suma de sus dígitos.
Soluciones
-- 1ª definición -- ============= especiales :: Integer -> [Integer] especiales n = [x | x <- [(10^n-1) `div` 9..10^n-1] , esEspecial x] esEspecial :: Integer -> Bool esEspecial x = 0 `notElem` digitos && x `mod` sum digitos == 0 where digitos = [read [d] | d <- show x] -- 2ª definición -- ============= especiales2 :: Integer -> [Integer] especiales2 n = [ m | (m, s) <- generador n , m `mod` s == 0] -- (generador n) es la lista de los pares formados por los números con n -- dígitos distintos de 0 junto son la suma de sus dígitos. Por ejemplo, -- λ> generador 2 -- [(11,2), (12,3), (13,4), (14,5), (15,6), (16,7), (17,8), (18,9), (19,10), -- (21,3), (22,4), (23,5), (24,6), (25,7), (26,8), (27,9), (28,10),(29,11), -- (31,4), (32,5), (33,6), (34,7), (35,8), (36,9), (37,10),(38,11),(39,12), -- (41,5), (42,6), (43,7), (44,8), (45,9), (46,10),(47,11),(48,12),(49,13), -- (51,6), (52,7), (53,8), (54,9), (55,10),(56,11),(57,12),(58,13),(59,14), -- (61,7), (62,8), (63,9), (64,10),(65,11),(66,12),(67,13),(68,14),(69,15), -- (71,8), (72,9), (73,10),(74,11),(75,12),(76,13),(77,14),(78,15),(79,16), -- (81,9), (82,10),(83,11),(84,12),(85,13),(86,14),(87,15),(88,16),(89,17), -- (91,10),(92,11),(93,12),(94,13),(95,14),(96,15),(97,16),(98,17),(99,18)] generador :: Integer -> [(Integer, Integer)] generador 0 = [(0,0)] generador n = [(m*10+c, s+c) | (m,s) <- generador (n-1) , c <- [1..9] ] -- Eficiencia -- ========== -- λ> :set +s -- λ> null (especiales 2000) -- False -- (28.02 secs, 11726529808 bytes) -- λ> null (especialesA7 2000) -- False -- (0.04 secs, 6036972 bytes)