-- | -- Module : Triangulares_con_cifras -- Description : Números triangulares con n cifras distintas. -- Copyright : Exercitium (27-05-14) -- License : GPL-3 -- Maintainer : JoseA.Alonso@gmail.com -- -- __Números triangulares con n cifras distintas__ -- -- Los números triangulares se forman como sigue -- -- > * * * -- > * * * * -- > * * * -- > 1 3 6 -- -- La sucesión de los números triangulares se obtiene sumando los -- números naturales. Así, los 5 primeros números triangulares son -- -- > 1 = 1 -- > 3 = 1+2 -- > 6 = 1+2+3 -- > 10 = 1+2+3+4 -- > 15 = 1+2+3+4+5 -- -- Definir la función -- -- > triangularesConCifras :: Int -> [Integer] -- -- tal que __(triangulares n)__ es la lista de los números triangulares con -- n cifras distintas. Por ejemplo, -- -- >>> take 6 (triangularesConCifras 1) -- [1,3,6,55,66,666] -- >>> take 6 (triangularesConCifras 2) -- [10,15,21,28,36,45] -- >>> take 6 (triangularesConCifras 3) -- [105,120,136,153,190,210] -- >>> take 5 (triangularesConCifras 4) -- [1035,1275,1326,1378,1485] -- >>> take 2 (triangularesConCifras 10) -- [1062489753,1239845706] module Triangulares_con_cifras where import Data.List (nub) -- | Definición. triangularesConCifras :: Int -> [Integer] triangularesConCifras n = [x | x <- triangulares , nCifras x == n] -- | __triangulares__ es la sucesión de los números triangulares. Por -- ejemplo, -- -- >>> take 15 triangulares1 -- [1,3,6,10,15,21,28,36,45,55,66,78,91,105,120] triangulares1 :: [Integer] triangulares1 = 1 : [x+y | (x,y) <- zip [2..] triangulares1] -- | 2ª definición de 'triangulares' (usando 'zipWith'). triangulares2 :: [Integer] triangulares2 = 1 : zipWith (+) [2..] triangulares1 -- | 3ª definición de 'triangulares' (usando 'scanl'). triangulares3 :: [Integer] triangulares3 = scanl (+) 1 [2..] -- | 4ª definición de triangulares (con la fórmula) triangulares4 :: [Integer] triangulares4 = [(n*(n+1)) `div` 2 | n <- [1..]] -- | __(prop_triangulares n)__ se verifica si las definiciones de -- triangulares son equivalentes en sus primeros n términos. Por -- ejemplo, -- -- >>> prop_triangulares 100 -- True prop_triangulares :: Int -> Bool prop_triangulares n = all (== take n triangulares1) [take n f | f <- [ triangulares2 , triangulares3 , triangulares4 ]] -- $nota -- -- Comparación de eficiencia: -- -- > > sum (take (10^6) triangulares1) -- > 166667166667000000 -- > (1.07 secs, 475,647,576 bytes) -- > > sum (take (10^6) triangulares2) -- > 166667166667000000 -- > (1.23 secs, 667,646,128 bytes) -- > > sum (take (10^6) triangulares3) -- > 166667166667000000 -- > (0.50 secs, 370,832,960 bytes) -- > > sum (take (10^6) triangulares4) -- > 166667166667000000 -- > (1.09 secs, 489,997,432 bytes) -- | Usaremos como __triangulares__ la 3ª definición. triangulares :: [Integer] triangulares = triangulares3 -- | __(nCifras x)__ es el número de cifras distintas del número x. Por -- ejemplo, -- -- >>> nCifras 325275 -- 4 nCifras :: Integer -> Int nCifras = length . nub . show