Paridad del número de divisores
Definir la función
nDivisoresPar :: Integer -> Bool
tal que (nDivisoresPar n) se verifica si n tiene un número par de divisores. Por ejemplo,
nDivisoresPar 12 == True nDivisoresPar 16 == False nDivisoresPar (product [1..2*10^4]) == True
Soluciones
import Data.List (group) import Data.Numbers.Primes (primeFactors) -- 1ª definición -- ============= nDivisoresPar1 :: Integer -> Bool nDivisoresPar1 = even . length . divisores -- (divisores n) es la lista de los divisores de n. Por ejemplo, -- divisores 12 == [1,2,3,4,6,12] -- divisores 16 == [1,2,4,8,16] divisores :: Integer -> [Integer] divisores n = [x | x <- [1..n], n `mod` x == 0] -- 2ª definición -- ============= nDivisoresPar2 :: Integer -> Bool nDivisoresPar2 n = any odd (map length (group (primeFactors n))) -- Comparación de eficiencia -- ========================= -- λ> nDivisoresPar1 (10^7) -- True -- (14.18 secs, 2,078,736,992 bytes) -- λ> nDivisoresPar2 (10^7) -- True -- (0.01 secs, 0 bytes) -- -- λ> nDivisoresPar2 (product [1..2*10^4]) -- True -- (2.30 secs, 1,003,013,112 bytes)
Solución en Maxima
/* concat(xs) es la lista obtenida concatenado los elementos de xss. Por ejemplo, concat([[1,3],[2,4],[5,7]]) == [1, 3, 2, 4, 5, 7] */ concat (xs) := block ([r:[]], for x in reverse (xs) do r : append (x,r), r)$ nDivisoresPares (n) := block( [xs : concat (map (rest, ifactors (n))), p : false], for x in xs do p: oddp (x) or p, p)$