Parejas de números y divisores
Definir la función
divisoresHasta :: Int -> [(Int,Int)]
tal que (divisoresHasta n) es la lista de los pares (a,b) tales que a es un número entre 2 y n y b es un divisor propio de a. Por ejemplo,
λ> divisoresHasta 6 [(2,1),(3,1),(4,1),(5,1),(6,1),(4,2),(6,2),(6,3)] λ> divisoresHasta 8 [(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(4,2),(6,2),(8,2),(6,3),(8,4)] λ> length (divisoresHasta 1234567) 16272448
Soluciones
import Data.List (sort, sortBy) import Data.Ord (comparing) import Data.Tuple (swap) -- 1ª definición -- ============= divisoresHasta1 :: Integer -> [(Integer,Integer)] divisoresHasta1 n = ordena (concat [[(a,b) | b <- divisoresPropios a] | a <- [2..n]]) where intercambia (x,y) = (y,x) ordena ps = [intercambia p | p <- sort (map intercambia ps)] divisoresPropios :: Integer -> [Integer] divisoresPropios n = [x | x <- [1..n-1], n `mod` x == 0] -- 2ª definición -- ============= divisoresHasta2 :: Integer -> [(Integer,Integer)] divisoresHasta2 n = ordena (concat [[(a,b) | b <- divisoresPropios a] | a <- [2..n]]) where ordena = sortBy comp comp (x,y) (u,v) = compare (y,x) (v,u) -- 3ª definición -- ============= divisoresHasta3 :: Integer -> [(Integer,Integer)] divisoresHasta3 n = ordena (concat [[(a,b) | b <- divisoresPropios a] | a <- [2..n]]) where ordena = sortBy (comparing swap) -- 4ª definición -- ============= divisoresHasta4 :: Integer -> [(Integer,Integer)] divisoresHasta4 n = [(a,b) | b <- [1..n], a <- [b+b, b+b+b..n]] -- Comparaciones de eficiencia -- =========================== -- λ> length (divisoresHasta1 3000) -- 21496 -- (6.14 secs, 967750416 bytes) -- -- λ> length (divisoresHasta2 3000) -- 21496 -- (6.27 secs, 993527816 bytes) -- -- λ> length (divisoresHasta3 3000) -- 21496 -- (6.14 secs, 991442120 bytes) -- -- λ> length (divisoresHasta4 3000) -- 21496 -- (0.02 secs, 6224480 bytes)