Número de divisores compuestos
Definir la función
1 |
nDivisoresCompuestos :: Integer -> Integer |
tal que (nDivisoresCompuestos x) es el número de divisores de x que son compuestos (es decir, números mayores que 1 que no son primos). Por ejemplo,
1 2 3 4 |
nDivisoresCompuestos 30 == 4 nDivisoresCompuestos (product [1..11]) == 534 nDivisoresCompuestos (product [1..25]) == 340022 length (show (nDivisoresCompuestos (product [1..3*10^4]))) == 1948 |
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 92 93 94 95 96 |
import Data.List (genericLength, group, inits, sort) import Data.Numbers.Primes (primeFactors) import Test.QuickCheck -- 1ª solución -- =========== -- nDivisoresCompuestos 30 == 4 nDivisoresCompuestos :: Integer -> Integer nDivisoresCompuestos = genericLength . divisoresCompuestos -- (divisoresCompuestos x) es la lista de los divisores de x que -- son números compuestos (es decir, números mayores que 1 que no son -- primos). Por ejemplo, -- divisoresCompuestos 30 == [6,10,15,30] divisoresCompuestos :: Integer -> [Integer] divisoresCompuestos = sort . map product . compuestos . map concat . productoCartesiano . map inits . group . primeFactors where compuestos xss = [xs | xs <- xss, length xs > 1] -- (productoCartesiano xss) es el producto cartesiano de los conjuntos xss. Por -- ejemplo, -- λ> productoCartesiano [[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ª solución -- =========== nDivisoresCompuestos2 :: Integer -> Integer nDivisoresCompuestos2 x = nDivisores x - nDivisoresPrimos x - 1 -- (nDivisores x) es el número de divisores de x. Por ejemplo, -- nDivisores 30 == 8 nDivisores :: Integer -> Integer nDivisores x = product [1 + genericLength xs | xs <- group (primeFactors x)] -- (nDivisoresPrimos x) es el número de divisores primos de x. Por -- ejemplo, -- nDivisoresPrimos 30 == 3 nDivisoresPrimos :: Integer -> Integer nDivisoresPrimos = genericLength . group . primeFactors -- 3ª solución -- =========== nDivisoresCompuestos3 :: Integer -> Integer nDivisoresCompuestos3 x = nDivisores - nDivisoresPrimos - 1 where xss = group (primeFactors x) nDivisores = product [1 + genericLength xs | xs <-xss] nDivisoresPrimos = genericLength xss -- Equivalencia de las definiciones -- ================================ -- La propiedad es prop_nDivisoresCompuestos :: (Positive Integer) -> Bool prop_nDivisoresCompuestos (Positive x) = all (== nDivisoresCompuestos x) [f x | f <- [ nDivisoresCompuestos2 , nDivisoresCompuestos3 ]] -- La comprobación es -- λ> quickCheck prop_nDivisoresCompuestos -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- λ> nDivisoresCompuestos (product [1..25]) -- 340022 -- (2.04 secs, 2,232,146,776 bytes) -- λ> nDivisoresCompuestos2 (product [1..25]) -- 340022 -- (0.00 secs, 220,192 bytes) -- -- λ> length (show (nDivisoresCompuestos2 (product [1..3*10^4]))) -- 1948 -- (5.22 secs, 8,431,630,288 bytes) -- λ> length (show (nDivisoresCompuestos3 (product [1..3*10^4]))) -- 1948 -- (3.06 secs, 4,662,277,664 bytes) |
Pensamiento
«Lo corriente en el hombre es la tendencia a creer verdadero cuanto le
reporta alguna utilidad. Por eso hay tantos hombres capaces de comulgar
con ruedas de molino.»Antonio Machado