{"id":7702,"date":"2022-04-09T12:10:16","date_gmt":"2022-04-09T10:10:16","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=7702"},"modified":"2022-04-09T12:10:16","modified_gmt":"2022-04-09T10:10:16","slug":"la-semana-en-exercitium-del-4-al-8-de-abril","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/la-semana-en-exercitium-del-4-al-8-de-abril\/","title":{"rendered":"La semana en Exercitium (del 4 al 8 de abril)"},"content":{"rendered":"<p>Esta semana he publicado en <a href=\"http:\/\/bit.ly\/2sqPtGs\">Exercitium<\/a> las soluciones de los siguientes problemas:<\/p>\n<ul>\n<li><a href=\"#ej1\">1. Mayor producto de las ramas de un \u00e1rbol<\/a><\/li>\n<li><a href=\"#ej2\">2. Diferencia sim\u00e9trica<\/a><\/li>\n<li><a href=\"#ej3\">3. Conjunto de primos relativos<\/a><\/li>\n<li><a href=\"#ej4\">4. Familias de n\u00fameros con alg\u00fan d\u00edgito en com\u00fan<\/a><\/li>\n<li><a href=\"#ej5\">5. Biparticiones de una lista<\/a><\/li>\n<\/ul>\n<p>A continuaci\u00f3n se muestran las soluciones.<br \/>\n<!--more--><br \/>\n<a name=\"ej1\"><\/a><\/p>\n<h3>1. Mayor producto de las ramas de un \u00e1rbol<\/h3>\n<p>Los \u00e1rboles se pueden representar mediante el siguiente tipo de datos<\/p>\n<pre lang=\"text\">\n   data Arbol a = N a [Arbol a]\n     deriving Show\n<\/pre>\n<p>Por ejemplo, los \u00e1rboles<\/p>\n<pre lang=\"text\">\n      1              3\n    \/  \\            \/|\\\n   2   3           \/ | \\\n       |          5  4  7\n       4          |     \/\\\n                  6    2  1\n<\/pre>\n<p>se representan por<\/p>\n<pre lang=\"text\">\n   ej1, ej2 :: Arbol Int\n   ej1 = N 1 [N 2 [],N 3 [N 4 []]]\n   ej2 = N 3 [N 5 [N 6 []], N 4 [], N 7 [N 2 [], N 1 []]]\n<\/pre>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   mayorProducto :: (Ord a, Num a) => Arbol a -> a\n<\/pre>\n<p>tal que <code>(mayorProducto a)<\/code> es el mayor producto de las ramas del \u00e1rbol <code>a<\/code>. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   \u03bb> mayorProducto (N 1 [N 2 [], N  3 []])\n   3\n   \u03bb> mayorProducto (N 1 [N 8 [], N  4 [N 3 []]])\n   12\n   \u03bb> mayorProducto (N 1 [N 2 [],N 3 [N 4 []]])\n   12\n   \u03bb> mayorProducto (N 3 [N 5 [N 6 []], N 4 [], N 7 [N 2 [], N 1 []]])\n   90\n   \u03bb> mayorProducto (N (-8) [N 0 [N (-9) []],N 6 []])\n   0\n   \u03bb> a = N (-4) [N (-7) [],N 14 [N 19 []],N (-1) [N (-6) [],N 21 []],N (-4) []]\n   \u03bb> mayorProducto a\n   84\n<\/pre>\n<h4>Soluciones<\/h4>\n<pre lang=\"haskell\">\nimport Test.QuickCheck\n\ndata Arbol a = N a [Arbol a]\n  deriving Show\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nmayorProducto1 :: (Ord a, Num a) => Arbol a -> a\nmayorProducto1 a = maximum [product xs | xs <- ramas a]\n\n-- (ramas a) es la lista de las ramas del \u00e1rbol a. Por ejemplo,\n--    \u03bb> ramas (N 3 [N 5 [N 6 []], N 4 [], N 7 [N 2 [], N 1 []]])\n--    [[3,5,6],[3,4],[3,7,2],[3,7,1]]\nramas :: Arbol b -> [[b]]\nramas (N x []) = [[x]]\nramas (N x as) = [x : xs | a <- as, xs <- ramas a]\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nmayorProducto2 :: (Ord a, Num a) => Arbol a -> a\nmayorProducto2 a = maximum (map product (ramas a))\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nmayorProducto3 :: (Ord a, Num a) => Arbol a -> a\nmayorProducto3 = maximum . map product . ramas\n\n-- 4\u00ba soluci\u00f3n\n-- ===========\n\nmayorProducto4 :: (Ord a, Num a) => Arbol a -> a\nmayorProducto4 = maximum . productosRamas\n\n-- (productosRamas a) es la lista de los productos de las ramas\n-- del \u00e1rbol a. Por ejemplo,\n--    \u03bb> productosRamas (N 3 [N 5 [N 6 []], N 4 [], N 7 [N 2 [], N 1 []]])\n--    [90,12,42,21]\nproductosRamas :: (Ord a, Num a) => Arbol a -> [a]\nproductosRamas (N x []) = [x]\nproductosRamas (N x xs) = [x * y | a <- xs, y <- productosRamas a]\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nmayorProducto5 :: (Ord a, Num a) => Arbol a -> a\nmayorProducto5 (N x []) = x\nmayorProducto5 (N x xs)\n  | x > 0     = x * maximum (map mayorProducto5 xs)\n  | x == 0    = 0\n  | otherwise = x * minimum (map menorProducto xs)\n\n-- (menorProducto a) es el menor producto de las ramas del \u00e1rbol\n-- a. Por ejemplo,\n--    \u03bb> menorProducto (N 1 [N 2 [], N  3 []])\n--    2\n--    \u03bb> menorProducto (N 1 [N 8 [], N  4 [N 3 []]])\n--    8\n--    \u03bb> menorProducto (N 1 [N 2 [],N 3 [N 4 []]])\n--    2\n--    \u03bb> menorProducto (N 3 [N 5 [N 6 []], N 4 [], N 7 [N 2 [], N 1 []]])\n--    12\nmenorProducto :: (Ord a, Num a) => Arbol a -> a\nmenorProducto (N x []) = x\nmenorProducto (N x xs)\n  | x > 0     = x * minimum (map menorProducto xs)\n  | x == 0    = 0\n  | otherwise = x * maximum (map mayorProducto2 xs)\n\n-- 6\u00aa soluci\u00f3n\n-- ===========\n\nmayorProducto6 :: (Ord a, Num a) => Arbol a -> a\nmayorProducto6 = maximum . aux\n  where aux (N a []) = [a]\n        aux (N a b)  = [v,u]\n          where u = maximum g\n                v = minimum g\n                g = map (*a) (concatMap aux b)\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- (arbolArbitrario n) es un \u00e1rbol aleatorio de orden n. Por ejemplo,\n--   > sample (arbolArbitrario 5 :: Gen (Arbol Int))\n--   N 0 [N 0 []]\n--   N (-2) []\n--   N 4 []\n--   N 2 [N 4 []]\n--   N 8 []\n--   N (-2) [N (-9) [],N 7 []]\n--   N 11 []\n--   N (-11) [N 4 [],N 14 []]\n--   N 10 [N (-3) [],N 13 []]\n--   N 12 [N 11 []]\n--   N 20 [N (-18) [],N (-13) []]\narbolArbitrario :: Arbitrary a => Int -> Gen (Arbol a)\narbolArbitrario n = do\n  x  <- arbitrary\n  ms <- sublistOf [0 .. n `div` 2]\n  as <- mapM arbolArbitrario ms\n  return (N x as)\n\n-- Arbol es una subclase de Arbitraria\ninstance Arbitrary a => Arbitrary (Arbol a) where\n  arbitrary = sized arbolArbitrario\n\n-- La propiedad es\nprop_mayorProducto :: Arbol Integer -> Bool\nprop_mayorProducto a =\n  all (== mayorProducto1 a)\n      [f a | f <- [ mayorProducto2\n                  , mayorProducto3\n                  , mayorProducto4\n                  , mayorProducto5\n                  , mayorProducto6\n                  ]]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_mayorProducto\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> ejArbol <- generate (arbolArbitrario 600 :: Gen (Arbol Integer))\n--    \u03bb> mayorProducto1 ejArbol\n--    2419727651266241493467136000\n--    (1.87 secs, 1,082,764,480 bytes)\n--    \u03bb> mayorProducto2 ejArbol\n--    2419727651266241493467136000\n--    (1.57 secs, 1,023,144,008 bytes)\n--    \u03bb> mayorProducto3 ejArbol\n--    2419727651266241493467136000\n--    (1.55 secs, 1,023,144,248 bytes)\n--    \u03bb> mayorProducto4 ejArbol\n--    2419727651266241493467136000\n--    (1.60 secs, 824,473,800 bytes)\n--    \u03bb> mayorProducto5 ejArbol\n--    2419727651266241493467136000\n--    (0.83 secs, 732,370,352 bytes)\n--    \u03bb> mayorProducto6 ejArbol\n--    2419727651266241493467136000\n--    (0.98 secs, 817,473,344 bytes)\n--\n--    \u03bb> ejArbol2 <- generate (arbolArbitrario 700 :: Gen (Arbol Integer))\n--    \u03bb> mayorProducto5 ejArbol2\n--    1044758937398026715504640000000\n--    (4.94 secs, 4,170,324,376 bytes)\n--    \u03bb> mayorProducto6 ejArbol2\n--    1044758937398026715504640000000\n--    (5.88 secs, 4,744,782,024 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Mayor_producto_de_las_ramas_de_un_arbol.hs\">GitHub<\/a>.<\/p>\n<p>La elaboraci\u00f3n de las soluciones se describe en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/Q38cb9YlDR0\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p><a name=\"ej2\"><\/a><\/p>\n<h3>2. Diferencia sim\u00e9trica<\/h3>\n<p>La <a href=\"http:\/\/bit.ly\/1Rdcqxs\">diferencia sim\u00e9trica<\/a> de dos conjuntos es el conjunto cuyos elementos son aquellos que pertenecen a alguno de los conjuntos iniciales, sin pertenecer a ambos a la vez. Por ejemplo, la diferencia sim\u00e9trica de {2,5,3} y {4,2,3,7} es {5,4,7}.<\/p>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   diferenciaSimetrica :: Ord a => [a] -> [a] -> [a]\n<\/pre>\n<p>tal que <code>(diferenciaSimetrica xs ys)<\/code> es la diferencia sim\u00e9trica de <code>xs<\/code> e <code>ys<\/code>. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   diferenciaSimetrica [2,5,3] [4,2,3,7]    ==  [4,5,7]\n   diferenciaSimetrica [2,5,3] [5,2,3]      ==  []\n   diferenciaSimetrica [2,5,2] [4,2,3,7]    ==  [3,4,5,7]\n   diferenciaSimetrica [2,5,2] [4,2,4,7]    ==  [4,5,7]\n   diferenciaSimetrica [2,5,2,4] [4,2,4,7]  ==  [5,7]\n<\/pre>\n<h4>Soluciones<\/h4>\n<pre lang=\"haskell\">\nimport Test.QuickCheck\nimport Data.List ((\\\\), intersect, nub, sort, union)\nimport qualified Data.Set as S\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\ndiferenciaSimetrica1 :: Ord a => [a] -> [a] -> [a]\ndiferenciaSimetrica1 xs ys =\n  sort (nub ([x | x <- xs, x `notElem` ys] ++ [y | y <- ys, y `notElem` xs]))\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\ndiferenciaSimetrica2 :: Ord a => [a] -> [a] -> [a]\ndiferenciaSimetrica2 xs ys =\n  sort (nub (filter (`notElem` ys) xs ++ filter (`notElem` xs) ys))\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\ndiferenciaSimetrica3 :: Ord a => [a] -> [a] -> [a]\ndiferenciaSimetrica3 xs ys =\n  sort (nub (union xs ys \\\\ intersect xs ys))\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\ndiferenciaSimetrica4 :: Ord a => [a] -> [a] -> [a]\ndiferenciaSimetrica4 xs ys =\n  [x | x <- sort (nub (xs ++ ys))\n     , x `notElem` xs || x `notElem` ys]\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\ndiferenciaSimetrica5 :: Ord a => [a] -> [a] -> [a]\ndiferenciaSimetrica5 xs ys =\n  S.elems ((xs' `S.union` ys') `S.difference` (xs' `S.intersection` ys'))\n  where xs' = S.fromList xs\n        ys' = S.fromList ys\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- La propiedad es\nprop_diferenciaSimetrica :: [Int] -> [Int] -> Bool\nprop_diferenciaSimetrica xs ys =\n  all (== diferenciaSimetrica1 xs ys)\n      [diferenciaSimetrica2 xs ys,\n       diferenciaSimetrica3 xs ys,\n       diferenciaSimetrica4 xs ys,\n       diferenciaSimetrica5 xs ys]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_diferenciaSimetrica\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> length (diferenciaSimetrica1 [1..2*10^4] [2,4..2*10^4])\n--    10000\n--    (2.34 secs, 10,014,360 bytes)\n--    \u03bb> length (diferenciaSimetrica2 [1..2*10^4] [2,4..2*10^4])\n--    10000\n--    (2.41 secs, 8,174,264 bytes)\n--    \u03bb> length (diferenciaSimetrica3 [1..2*10^4] [2,4..2*10^4])\n--    10000\n--    (5.84 secs, 10,232,006,288 bytes)\n--    \u03bb> length (diferenciaSimetrica4 [1..2*10^4] [2,4..2*10^4])\n--    10000\n--    (5.83 secs, 14,814,184 bytes)\n--    \u03bb> length (diferenciaSimetrica5 [1..2*10^4] [2,4..2*10^4])\n--    10000\n--    (0.02 secs, 7,253,496 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Diferencia_simetrica.hs\">GitHub<\/a>.<\/p>\n<p>La elaboraci\u00f3n de las soluciones se describe en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/ebQ_u6xlVfQ\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p><a name=\"ej3\"><\/a><\/p>\n<h3>3. Conjunto de primos relativos<\/h3>\n<p>Dos n\u00fameros enteros positivos son <a href=\"http:\/\/bit.ly\/1xgqDTK\">primos relativos<\/a> si no tienen ning\u00fan factor primo en com\u00fan; es decit, si 1 es su \u00fanico divisor com\u00fan.  Por ejemplo, 6 y 35 son primos entre s\u00ed, pero 6 y 27 no lo son porque ambos son divisibles por 3.<\/p>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   primosRelativos :: [Int] -> Bool\n<\/pre>\n<p>tal que <code>(primosRelativos xs)<\/code> se verifica si los elementos de <code>xs<\/code> son primos relativos dos a dos. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   primosRelativos [6,35]         ==  True\n   primosRelativos [6,27]         ==  False\n   primosRelativos [2,3,4]        ==  False\n   primosRelativos [6,35,11]      ==  True\n   primosRelativos [6,35,11,221]  ==  True\n   primosRelativos [6,35,11,231]  ==  False\n<\/pre>\n<h4>Soluciones<\/h4>\n<pre lang=\"haskell\">\nimport Test.QuickCheck\nimport Data.List (delete, intersect)\nimport Data.Numbers.Primes (primeFactors, primes)\nimport qualified Data.Set as S (disjoint, fromList)\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nprimosRelativos1 :: [Int] -> Bool\nprimosRelativos1 []     = True\nprimosRelativos1 (x:xs) =\n  and [sonPrimosRelativos1 x y | y <- xs] &#038;&#038; primosRelativos1 xs\n\n-- (sonPrimosRelativos x y) se verifica si x e y son primos\n-- relativos. Por ejemplo,\n--    sonPrimosRelativos1 6 35  ==  True\n--    sonPrimosRelativos1 6 27  ==  False\nsonPrimosRelativos1 :: Int -> Int -> Bool\nsonPrimosRelativos1 x y =\n  null (divisoresPrimos x `intersect` divisoresPrimos y)\n\n-- (divisoresPrimos x) es la lista de los divisores primos de x. Por\n-- ejemplo,\n--    divisoresPrimos 600  ==  [2,2,2,3,5,5]\ndivisoresPrimos :: Int -> [Int]\ndivisoresPrimos 1 = []\ndivisoresPrimos x =\n  y : divisoresPrimos (x `div` y)\n  where y = menorDivisorPrimo x\n\n-- (menorDivisorPrimo x) es el menor divisor primo de x. Por ejemplo,\n--    menorDivisorPrimo 15  ==  3\n--    menorDivisorPrimo 11  ==  11\nmenorDivisorPrimo :: Int -> Int\nmenorDivisorPrimo x =\n  head [y | y <- [2..], x `mod` y == 0]\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nprimosRelativos2 :: [Int] -> Bool\nprimosRelativos2 []     = True\nprimosRelativos2 (x:xs) =\n  all (sonPrimosRelativos1 x) xs && primosRelativos2 xs\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nprimosRelativos3 :: [Int] -> Bool\nprimosRelativos3 []     = True\nprimosRelativos3 (x:xs) =\n  all (sonPrimosRelativos2 x) xs && primosRelativos3 xs\n\nsonPrimosRelativos2 :: Int -> Int -> Bool\nsonPrimosRelativos2 x y =\n  null (primeFactors x `intersect` primeFactors y)\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\nprimosRelativos4 :: [Int] -> Bool\nprimosRelativos4 []     = True\nprimosRelativos4 (x:xs) =\n  all (sonPrimosRelativos3 x) xs && primosRelativos4 xs\n\nsonPrimosRelativos3 :: Int -> Int -> Bool\nsonPrimosRelativos3 x y =\n  S.fromList (primeFactors x) `S.disjoint` S.fromList (primeFactors y)\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nprimosRelativos5 :: [Int] -> Bool\nprimosRelativos5 []     = True\nprimosRelativos5 (x:xs) =\n  all (sonPrimosRelativos5 x) xs && primosRelativos5 xs\n\nsonPrimosRelativos5 :: Int -> Int -> Bool\nsonPrimosRelativos5 x y =\n  gcd x y == 1\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- La propiedad es\nprop_primosRelativos :: [Positive Int] -> Bool\nprop_primosRelativos xs =\n  all (== primosRelativos1 ys)\n      [primosRelativos2 ys,\n       primosRelativos3 ys,\n       primosRelativos4 ys,\n       primosRelativos5 ys]\n  where ys = getPositive <$> xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_primosRelativos\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> primosRelativos1 (take 120 primes)\n--    True\n--    (1.92 secs, 869,909,416 bytes)\n--    \u03bb> primosRelativos2 (take 120 primes)\n--    True\n--    (1.99 secs, 869,045,656 bytes)\n--    \u03bb> primosRelativos3 (take 120 primes)\n--    True\n--    (0.09 secs, 221,183,200 bytes)\n--\n--    \u03bb> primosRelativos3 (take 600 primes)\n--    True\n--    (2.62 secs, 11,196,690,856 bytes)\n--    \u03bb> primosRelativos4 (take 600 primes)\n--    True\n--    (2.66 secs, 11,190,940,456 bytes)\n--    \u03bb> primosRelativos5 (take 600 primes)\n--    True\n--    (0.14 secs, 123,673,648 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Conjunto_de_primos_relativos.hs\">GitHub<\/a>.<\/p>\n<p>La elaboraci\u00f3n de las soluciones se describe en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/OCHmRQ4XwbU\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p><a name=\"ej4\"><\/a><\/p>\n<h3>4. Familias de n\u00fameros con alg\u00fan d\u00edgito en com\u00fan<\/h3>\n<p>Una familia de n\u00fameros es una lista de n\u00fameros tal que todos tienen la misma cantidad de d\u00edgitos y, adem\u00e1s, dichos n\u00fameros tienen al menos un d\u00edgito com\u00fan.<\/p>\n<p>Por ejemplo, los n\u00fameros 72, 32, 25 y 22 pertenecen a la misma familia ya que son n\u00fameros de dos d\u00edgitos y todos tienen el d\u00edgito 2, mientras que los n\u00fameros 123, 245 y 568 no pertenecen a la misma familia, ya que no hay un d\u00edgito que aparezca en los tres n\u00fameros.<\/p>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   esFamilia :: [Integer] -> Bool\n<\/pre>\n<p>tal que <code>(esFamilia ns)<\/code> se verifica si <code>ns<\/code> es una familia de n\u00fameros. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   esFamilia [72, 32, 25, 22]  ==  True\n   esFamilia [123,245,568]     ==  False\n   esFamilia [72, 32, 25, 223] ==  False\n   esFamilia [56]              ==  True\n   esFamilia []                ==  True\n<\/pre>\n<h4>Soluciones<\/h4>\n<pre lang=\"haskell\">\nimport Data.List (intersect, nub)\nimport Test.QuickCheck (quickCheck)\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nesFamilia1 :: [Integer] -> Bool\nesFamilia1 [] = True\nesFamilia1 ns =\n  igualNumeroElementos dss && tieneElementoComun dss\n  where dss = map show ns\n\n-- (igualNumeroElementos xss) se verifica si todas las listas de xss\n-- tienen el mismo n\u00famero de elementos. Por ejemplo,\n--    igualNumeroElementos [[1,3],[2,2],[4,9]]    ==  True\n--    igualNumeroElementos [[1,3],[2,1,2],[4,9]]  ==  False\nigualNumeroElementos :: [[a]] -> Bool\nigualNumeroElementos xss =\n  iguales (map length xss)\n\n-- (iguales xs) se verifica si todos los elementos de xs son\n-- iguales. Por ejemplo,\n--    iguales [3,3,3,3]  ==  True\n--    iguales [3,3,7,3]  ==  False\niguales :: Eq a => [a] -> Bool\niguales []     = True\niguales (x:xs) = all (==x) xs\n\n-- (tieneElementoComun xss) se verifican si todas las listas de xss\n-- tienen alg\u00fan elemento com\u00fan. Por ejemplo,\n--    tieneElementoComun [[1,2],[2,3],[4,2,7]]  ==  True\n--    tieneElementoComun [[1,2],[2,3],[4,3,7]]  ==  False\ntieneElementoComun :: Eq a => [[a]] -> Bool\ntieneElementoComun []       = False\ntieneElementoComun (xs:xss) = any (`esElementoComun` xss) xs\n\n-- (esElementoComun x yss) se verifica si x pertenece a todos los\n-- elementos de yss. Por ejemplo,\n--    esElementoComun 2 [[1,2],[2,3],[4,2,7]]  ==  True\n--    esElementoComun 2 [[1,2],[2,3],[4,3,7]]  ==  False\nesElementoComun :: Eq a => a -> [[a]] -> Bool\nesElementoComun x = all (x `elem`)\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nesFamilia2 :: [Integer] -> Bool\nesFamilia2 [] = True\nesFamilia2 ns =\n  igualNumeroElementos2 dss && tieneElementoComun2 dss\n  where dss = map show ns\n\nigualNumeroElementos2 :: [[a]] -> Bool\nigualNumeroElementos2 xss =\n  length (nub (map length xss)) == 1\n\ntieneElementoComun2 :: Eq a => [[a]] -> Bool\ntieneElementoComun2 xss =\n  not (null (foldl1 intersect xss))\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nesFamilia3 :: [Integer] -> Bool\nesFamilia3 [] = True\nesFamilia3 ns =\n  igualNumeroElementos3 dss && tieneElementoComun3 dss\n  where dss = map show ns\n\nigualNumeroElementos3 :: [[a]] -> Bool\nigualNumeroElementos3 = ((==1) . length) . nub . map length\n\ntieneElementoComun3 :: Eq a => [[a]] -> Bool\ntieneElementoComun3 = (not . null) . foldl1 intersect\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- La propiedad es\nprop_esFamilia :: [Integer] -> Bool\nprop_esFamilia xss =\n  all (== esFamilia1 xss)\n      [esFamilia2 xss,\n       esFamilia3 xss]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_esFamilia\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> esFamilia1 [10^6..4*10^6]\n--    False\n--    (1.85 secs, 1,931,162,984 bytes)\n--    \u03bb> esFamilia2 [10^6..4*10^6]\n--    False\n--    (2.31 secs, 2,288,177,752 bytes)\n--    \u03bb> esFamilia3 [10^6..4*10^6]\n--    False\n--    (2.23 secs, 2,288,177,864 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Familias_de_numeros_con_algun_digito_en_comun.hs\">GitHub<\/a>.<\/p>\n<p>La elaboraci\u00f3n de las soluciones se describe en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/_uOlyfzppVc\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p><a name=\"ej5\"><\/a><\/p>\n<h3>5. Biparticiones de una lista<\/h3>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   biparticiones :: [a] -> [([a],[a])]\n<\/pre>\n<p>tal que <code>(biparticiones xs)<\/code> es la lista de pares formados por un prefijo de <code>xs<\/code> y el resto de <code>xs<\/code>. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   \u03bb> biparticiones [3,2,5]\n   [([],[3,2,5]),([3],[2,5]),([3,2],[5]),([3,2,5],[])]\n   \u03bb> biparticiones \"Roma\"\n   [(\"\",\"Roma\"),(\"R\",\"oma\"),(\"Ro\",\"ma\"),(\"Rom\",\"a\"),(\"Roma\",\"\")]\n<\/pre>\n<h4>Soluciones<\/h4>\n<pre lang=\"haskell\">\nimport Data.List (inits, tails)\nimport Control.Applicative (liftA2)\nimport Test.QuickCheck (quickCheck)\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nbiparticiones1 :: [a] -> [([a],[a])]\nbiparticiones1 [] = [([],[])]\nbiparticiones1 (x:xs) =\n  ([],(x:xs)) : [(x:ys,zs) | (ys,zs) <- biparticiones1 xs]\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nbiparticiones2 :: [a] -> [([a],[a])]\nbiparticiones2 xs =\n  [(take i xs, drop i xs) | i <- [0..length xs]]\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nbiparticiones3 :: [a] -> [([a],[a])]\nbiparticiones3 xs =\n  [splitAt i xs | i <- [0..length xs]]\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\nbiparticiones4 :: [a] -> [([a],[a])]\nbiparticiones4 xs =\n  zip (inits xs) (tails xs)\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nbiparticiones5 :: [a] -> [([a],[a])]\nbiparticiones5 = liftA2 zip inits tails\n\n-- 6\u00aa soluci\u00f3n\n-- ===========\n\nbiparticiones6 :: [a] -> [([a],[a])]\nbiparticiones6 = zip <$> inits <*> tails\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- La propiedad es\nprop_biparticiones :: [Int] -> Bool\nprop_biparticiones xs =\n  all (== biparticiones1 xs)\n      [biparticiones2 xs,\n       biparticiones3 xs,\n       biparticiones4 xs,\n       biparticiones5 xs,\n       biparticiones6 xs]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_biparticiones\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> length (biparticiones1 [1..6*10^3])\n--    6001\n--    (2.21 secs, 3,556,073,552 bytes)\n--    \u03bb> length (biparticiones2 [1..6*10^3])\n--    6001\n--    (0.01 secs, 2,508,448 bytes)\n--\n--    \u03bb> length (biparticiones2 [1..6*10^6])\n--    6000001\n--    (2.26 secs, 2,016,494,864 bytes)\n--    \u03bb> length (biparticiones3 [1..6*10^6])\n--    6000001\n--    (2.12 secs, 1,584,494,792 bytes)\n--    \u03bb> length (biparticiones4 [1..6*10^6])\n--    6000001\n--    (0.78 secs, 1,968,494,704 bytes)\n--    \u03bb> length (biparticiones5 [1..6*10^6])\n--    6000001\n--    (0.79 secs, 1,968,494,688 bytes)\n--    \u03bb> length (biparticiones6 [1..6*10^6])\n--    6000001\n--    (0.77 secs, 1,968,494,720 bytes)\n--\n--    \u03bb> length (biparticiones4 [1..10^7])\n--    10000001\n--    (1.30 secs, 3,280,495,432 bytes)\n--    \u03bb> length (biparticiones5 [1..10^7])\n--    10000001\n--    (1.42 secs, 3,280,495,416 bytes)\n--    \u03bb> length (biparticiones6 [1..10^7])\n--    10000001\n--    (1.30 secs, 3,280,495,448 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Biparticiones_de_una_lista.hs\">GitHub<\/a>.<\/p>\n<p>La elaboraci\u00f3n de las soluciones se describe en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/C8P3dYzFHXY\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Esta semana he publicado en Exercitium las soluciones de los siguientes problemas: 1. Mayor producto de las ramas de un \u00e1rbol 2. Diferencia sim\u00e9trica 3. Conjunto de primos relativos 4. Familias de n\u00fameros con alg\u00fan d\u00edgito en com\u00fan 5. Biparticiones de una lista A continuaci\u00f3n se muestran las soluciones.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[337],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7702"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/comments?post=7702"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7702\/revisions"}],"predecessor-version":[{"id":7703,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7702\/revisions\/7703"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=7702"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=7702"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=7702"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}