Ir al contenido principal

Número de divisores

Definir la función

numeroDivisores :: Integer -> Integer

tal que (numeroDivisores x) es el número de divisores de x. Por ejemplo,

numeroDivisores 12  ==  6
numeroDivisores 25  ==  3
length (show (numeroDivisores (product (take 20000 primes)))) == 6021

Soluciones

import Data.List (genericLength, group, inits, sort)
import Data.Numbers.Primes (primes, primeFactors)

-- 1ª definición
-- =============

numeroDivisores1 :: Integer -> Integer
numeroDivisores1 =
  genericLength . divisores

-- (divisores x) es la lista de los divisores de x. Por ejemplo,
--    divisores 12  ==  [1,2,3,4,6,12]
--      divisores 25  ==  [1,5,25]
divisores :: Integer -> [Integer]
divisores =
  sort
  . map (product . concat)
  . productoCartesiano
  . map inits
  . group
  . primeFactors

-- (producto xss) es el producto cartesiano de los conjuntos xss. Por
-- ejemplo,
--    λ> producto [[1,3],[2,5],[6,4]]
--    [[1,2,6],[1,2,4],[1,5,6],[1,5,4],[3,2,6],[3,2,4],[3,5,6],[3,5,4]]
productoCartesiano :: [[a]] -> [[a]]
productoCartesiano []       = [[]]
productoCartesiano (xs:xss) =
  [x:ys | x <- xs, ys <- productoCartesiano xss]

-- 2ª definición
-- =============

numeroDivisores2 :: Integer -> Integer
numeroDivisores2 =
  product . map ((+1) . genericLength) . group . primeFactors

-- Comparación de la eficiencia
-- ============================

--    λ> numeroDivisores1 (product [1..12])
--    792
--    (3.09 secs, 1,024,939,296 bytes)
--    λ> numeroDivisores2 (product [1..12])
--    792
--    (0.01 secs, 156,840 bytes)
--
--    λ> length (show (numeroDivisores1 (product (take 19 primes))))
--    6
--    (13.57 secs, 3,458,747,288 bytes)
--    λ> length (show (numeroDivisores2 (product (take 19 primes))))
--    6
--    (0.01 secs, 234,656 bytes)