Divisores de un número con final dado
Definir la función
divisoresConFinal :: Integer -> Integer -> [Integer]
tal que (divisoresConFinal n m)
es la lista de los divisores de n
cuyos dígitos finales coincide con m
. Por ejemplo,
divisoresConFinal 84 4 == [4,14,84] divisoresConFinal 720 20 == [20,120,720]
Soluciones
import Data.List (group, inits, isSuffixOf, nub, sort, subsequences) import Data.Numbers.Primes (primeFactors) import Test.Hspec (Spec, describe, hspec, it, shouldBe) import Test.QuickCheck -- 1ª solución -- =========== divisoresConFinal1 :: Integer -> Integer -> [Integer] divisoresConFinal1 n m = [x | x <- divisores1 n, final1 x m] -- (divisores n) es el conjunto de divisores de n. Por ejemplo, -- divisores 30 == [1,2,3,5,6,10,15,30] divisores1 :: Integer -> [Integer] divisores1 n = [x | x <- [1..n], n `rem` x == 0] -- (final x y) se verifica si el final de x es igual a y. Por ejemplo, -- final 325 5 == True -- final 325 25 == True -- final 325 35 == False final1 :: Integer -> Integer -> Bool final1 x y = take n xs == ys where xs = reverse (show x) ys = reverse (show y) n = length ys -- 2ª solución -- =========== divisoresConFinal2 :: Integer -> Integer -> [Integer] divisoresConFinal2 n m = [x | x <- divisores2 n, final2 x m] divisores2 :: Integer -> [Integer] divisores2 n = filter ((== 0) . mod n) [1..n] final2 :: Integer -> Integer -> Bool final2 x y = show y `isSuffixOf` show x -- 3ª solución -- =========== divisoresConFinal3 :: Integer -> Integer -> [Integer] divisoresConFinal3 n m = [x | x <- divisores3 n, final2 x m] divisores3 :: Integer -> [Integer] divisores3 = nub . sort . map product . subsequences . primeFactors -- 4ª solución -- =========== divisoresConFinal4 :: Integer -> Integer -> [Integer] divisoresConFinal4 n m = [x | x <- divisores4 n, final2 x m] divisores4 :: Integer -> [Integer] divisores4 = sort . map (product . concat) . productoCartesiano . map inits . group . primeFactors -- (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] -- 5ª solución -- =========== divisoresConFinal5 :: Integer -> Integer -> [Integer] divisoresConFinal5 n m = [x | x <- divisores5 n, final2 x m] divisores5 :: Integer -> [Integer] divisores5 = sort . map (product . concat) . sequence . map inits . group . primeFactors -- 6ª solución -- =========== divisoresConFinal6 :: Integer -> Integer -> [Integer] divisoresConFinal6 n m = [x | x <- divisores6 n, final2 x m] divisores6 :: Integer -> [Integer] divisores6 = sort . map (product . concat) . mapM inits . group . primeFactors -- Verificación -- ============ verifica :: IO () verifica = hspec spec specG :: (Integer -> Integer -> [Integer]) -> Spec specG divisoresConFinal = do it "e1" $ divisoresConFinal 84 4 `shouldBe` [4,14,84] it "e2" $ divisoresConFinal 720 20 `shouldBe` [20,120,720] spec :: Spec spec = do describe "def. 1" $ specG divisoresConFinal1 describe "def. 2" $ specG divisoresConFinal2 describe "def. 3" $ specG divisoresConFinal3 describe "def. 4" $ specG divisoresConFinal4 describe "def. 5" $ specG divisoresConFinal5 describe "def. 6" $ specG divisoresConFinal6 -- La verificación es -- λ> verifica -- 12examples, 0 failures -- Comprobación de equivalencia -- ============================ -- La propiedad es prop_divisoresConFinal :: Positive Integer -> Positive Integer -> Bool prop_divisoresConFinal (Positive n) (Positive m) = all (== divisoresConFinal1 n m) [ divisoresConFinal2 n m, divisoresConFinal3 n m, divisoresConFinal4 n m, divisoresConFinal5 n m, divisoresConFinal6 n m ] -- La comprobación es -- λ> quickCheck prop_divisoresConFinal -- +++ OK, passed 100 tests. -- Comparación de la eficiencia -- ============================ -- La comparación es -- λ> divisoresConFinal1 (product [1..11]) 6800 -- [16800,226800,316800,39916800] -- (13.89 secs, 7,984,560,800 bytes) -- λ> divisoresConFinal2 (product [1..11]) 6800 -- [16800,226800,316800,39916800] -- (4.84 secs, 4,790,920,688 bytes) -- λ> divisoresConFinal3 (product [1..11]) 6800 -- [16800,226800,316800,39916800] -- (0.07 secs, 87,137,992 bytes) -- λ> divisoresConFinal4 (product [1..11]) 6800 -- [16800,226800,316800,39916800] -- (0.02 secs, 2,324,528 bytes) -- λ> divisoresConFinal5 (product [1..11]) 6800 -- [16800,226800,316800,39916800] -- (0.00 secs, 1,801,872 bytes) -- λ> divisoresConFinal6 (product [1..11]) 6800 -- [16800,226800,316800,39916800] -- (0.01 secs, 1,801,536 bytes) -- -- λ> divisoresConFinal4 (product [1..25]) 985984000000 -- [2985984000000,95096985984000000,15511210043330985984000000] -- (1.77 secs, 2,142,500,832 bytes) -- λ> divisoresConFinal5 (product [1..25]) 985984000000 -- [2985984000000,95096985984000000,15511210043330985984000000] -- (1.15 secs, 1,603,330,352 bytes) -- λ> divisoresConFinal6 (product [1..25]) 985984000000 -- [2985984000000,95096985984000000,15511210043330985984000000] -- (1.19 secs, 1,603,329,840 bytes)