{"id":7693,"date":"2022-03-26T16:24:32","date_gmt":"2022-03-26T15:24:32","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=7693"},"modified":"2022-03-26T16:24:32","modified_gmt":"2022-03-26T15:24:32","slug":"la-semana-en-exercitium-del-21-al-25-de-marzo","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/la-semana-en-exercitium-del-21-al-25-de-marzo\/","title":{"rendered":"La semana en Exercitium (del 21 al 25 de marzo)"},"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. Valores de polinomios representados con vectores.<\/a><\/li>\n<li><a href=\"#ej2\">2. Ramas de un \u00e1rbol<\/a><\/li>\n<li><a href=\"#ej3\">3. Alfabeto comenzando en un car\u00e1cter<\/a><\/li>\n<li><a href=\"#ej4\">4. Numeraci\u00f3n de las ternas de n\u00fameros naturales.<\/a><\/li>\n<li><a href=\"#ej5\">5. Ordenaci\u00f3n de estructuras<\/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. Valores de polinomios representados con vectores.<\/h3>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- Los polinomios se pueden representar mediante vectores usando la\n-- librer\u00eda Data.Array. En primer lugar, se define el tipo de los\n-- polinomios (con coeficientes de tipo a) mediante\n--    type Polinomio a = Array Int a\n-- Como ejemplos, definimos el polinomio\n--    ej_pol1 :: Array Int Int\n--    ej_pol1 = array (0,4) [(0,6),(1,2),(2,-5),(3,0),(4,7)]\n-- que representa a 6 + 2x - 5x^2 + 7x^4 y el polinomio\n--    ej_pol2 :: Array Int Double\n--    ej_pol2 = array (0,4) [(0,6.5),(1,2),(2,-5.2),(3,0),(4,7)]\n-- que representa a 6.5 + 2x - 5.2x^2 + 7x^4\n--\n-- Definir la funci\u00f3n\n--    valor :: Num a => Polinomio a -> a -> a\n-- tal que (valor p b) es el valor del polinomio p en el punto b. Por\n-- ejemplo,\n--    valor ej_pol1 0  ==  6\n--    valor ej_pol1 1  ==  10\n--    valor ej_pol1 2  ==  102\n--    valor ej_pol2 0  ==  6.5\n--    valor ej_pol2 1  ==  10.3\n--    valor ej_pol2 3  ==  532.7\n--    length (show (valor (listArray (0,5*10^5) (repeat 1)) 2)) == 150516\n-- ---------------------------------------------------------------------\n\nimport Data.List (foldl')\nimport Data.Array (Array, (!), array, assocs, bounds, elems, listArray)\nimport Test.QuickCheck\n\ntype Polinomio a = Array Int a\n\nej_pol1 :: Array Int Int\nej_pol1 = array (0,4) [(0,6),(1,2),(2,-5),(3,0),(4,7)]\n\nej_pol2 :: Array Int Double\nej_pol2 = array (0,4) [(1,2),(2,-5.2),(4,7),(0,6.5),(3,0)]\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nvalor1 :: Num a => Polinomio a -> a -> a\nvalor1 p b = sum [(p!i)*b^i | i <- [0..n]]\n  where (_,n) = bounds p\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nvalor2 :: Num a => Polinomio a -> a -> a\nvalor2 p b = sum [(p!i)*b^i | i <- [0..length p - 1]]\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nvalor3 :: Num a => Polinomio a -> a -> a\nvalor3 p b = sum [v*b^i | (i,v) <- assocs p]\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\nvalor4 :: Num a => Polinomio a -> a -> a\nvalor4 = valorLista4 . elems\n\nvalorLista4 :: Num a => [a] -> a -> a\nvalorLista4 xs b =\n  sum [(xs !! i) * b^i | i <- [0..length xs - 1]]\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nvalor5 :: Num a => Polinomio a -> a -> a\nvalor5 = valorLista5 . elems\n\nvalorLista5 :: Num a => [a] -> a -> a\nvalorLista5 []     _ = 0\nvalorLista5 (x:xs) b = x + b * valorLista5 xs b\n\n-- 6\u00aa soluci\u00f3n\n-- ===========\n\nvalor6 :: Num a => Polinomio a -> a -> a\nvalor6 = valorLista6 . elems\n\nvalorLista6 :: Num a => [a] -> a -> a\nvalorLista6 xs b = aux xs\n  where aux []     = 0\n        aux (y:ys) = y + b * aux ys\n\n-- 7\u00aa soluci\u00f3n\n-- ===========\n\nvalor7 :: Num a => Polinomio a -> a -> a\nvalor7 = valorLista7 . elems\n\nvalorLista7 :: Num a => [a] -> a -> a\nvalorLista7 xs b = foldr (\\y r -> y + b * r) 0 xs\n\n-- 8\u00aa soluci\u00f3n\n-- ===========\n\nvalor8 :: Num a => Polinomio a -> a -> a\nvalor8 = valorLista8 . elems\n\nvalorLista8 :: Num a => [a] -> a -> a\nvalorLista8 xs b = aux 0 (reverse xs)\n  where aux r []     = r\n        aux r (y:ys) = aux (y + r * b) ys\n\n-- 9\u00aa soluci\u00f3n\n-- ===========\n\nvalor9 :: Num a => Polinomio a -> a -> a\nvalor9 = valorLista9 . elems\n\nvalorLista9 :: Num a => [a] -> a -> a\nvalorLista9 xs b = aux 0 (reverse xs)\n  where aux = foldl (\\ r y -> y + r * b)\n\n-- 10\u00aa soluci\u00f3n\n-- ============\n\nvalor10 :: Num a => Polinomio a -> a -> a\nvalor10 p b =\n  foldl (\\ r y -> y + r * b) 0 (reverse (elems p))\n\n-- 11\u00aa soluci\u00f3n\n-- ============\n\nvalor11 :: Num a => Polinomio a -> a -> a\nvalor11 p b =\n  foldl' (\\ r y -> y + r * b) 0 (reverse (elems p))\n\n-- 12\u00aa soluci\u00f3n\n-- ============\n\nvalor12 :: Num a => Polinomio a -> a -> a\nvalor12 p b =\n  sum (zipWith (*) (elems p) (iterate (* b) 1))\n\n-- 13\u00aa soluci\u00f3n\n-- ============\n\nvalor13 :: Num a => Polinomio a -> a -> a\nvalor13 p b =\n  foldl' (+) 0 (zipWith (*) (elems p) (iterate (* b) 1))\n\n-- Equivalencia de las definiciones\n-- ================================\n\n-- La propiedad es\nprop_valor :: [Integer] -> Integer -> Bool\nprop_valor xs b =\n  all (== valor1 p b)\n      [f p b | f <- [valor2,\n                     valor3,\n                     valor4,\n                     valor5,\n                     valor6,\n                     valor7,\n                     valor8,\n                     valor9,\n                     valor10,\n                     valor11,\n                     valor12,\n                     valor13]]\n  where p = listArray (0, length xs - 1) xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_valor\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> length (show (valor1 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (7.62 secs, 2,953,933,864 bytes)\n--    \u03bb> length (show (valor2 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (8.26 secs, 2,953,933,264 bytes)\n--    \u03bb> length (show (valor3 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (7.49 secs, 2,954,733,184 bytes)\n--    \u03bb> length (show (valor4 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (84.80 secs, 2,956,333,712 bytes)\n--    \u03bb> length (show (valor5 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (1.34 secs, 1,307,347,416 bytes)\n--    \u03bb> length (show (valor6 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (1.26 secs, 1,308,114,752 bytes)\n--    \u03bb> length (show (valor7 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (1.21 secs, 1,296,843,456 bytes)\n--    \u03bb> length (show (valor8 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (1.28 secs, 1,309,591,744 bytes)\n--    \u03bb> length (show (valor9 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (1.27 secs, 1,299,191,672 bytes)\n--    \u03bb> length (show (valor10 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (1.30 secs, 1,299,191,432 bytes)\n--    \u03bb> length (show (valor11 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (0.23 secs, 1,287,654,752 bytes)\n--    \u03bb> length (show (valor12 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (0.75 secs, 1,309,506,968 bytes)\n--    \u03bb> length (show (valor13 (listArray (0,10^5) (repeat 1)) 2))\n--    30104\n--    (0.22 secs, 1,298,867,128 bytes)\n<\/pre>\n<p>La elaboraci\u00f3n de las soluciones se encuentran en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/JuCmeb8vV4E\" 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. Ramas de un \u00e1rbol<\/h3>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- Los \u00e1rboles se pueden representar mediante el siguiente tipo de datos\n--    data Arbol a = N a [Arbol a]\n--                   deriving Show\n-- Por ejemplo, los \u00e1rboles\n--      1               3\n--     \/ \\             \/|\\\n--    2   3           \/ | \\\n--        |          5  4  7\n--        4          |     \/\\\n--                   6    2  1\n-- se representan por\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--\n-- Definir la funci\u00f3n\n--    ramas :: Arbol b -> [[b]]\n-- tal que (ramas a) es la lista de las ramas del \u00e1rbol a. Por ejemplo,\n--    ramas ej1  ==  [[1,2],[1,3,4]]\n--    ramas ej2  ==  [[3,5,6],[3,4],[3,7,2],[3,7,1]]\n-- ---------------------------------------------------------------------\n\nimport Test.QuickCheck\n\ndata Arbol a = N a [Arbol a]\n  deriving Show\n\nej1, ej2 :: Arbol Int\nej1 = N 1 [N 2 [],N 3 [N 4 []]]\nej2 = N 3 [N 5 [N 6 []], N 4 [], N 7 [N 2 [], N 1 []]]\n\n-- 1\u00aa soluci\u00f3n\nramas1 :: Arbol b -> [[b]]\nramas1 (N x []) = [[x]]\nramas1 (N x as) = [x : xs | a <- as, xs <- ramas1 a]\n\n-- 2\u00aa soluci\u00f3n\nramas2 :: Arbol b -> [[b]]\nramas2 (N x []) = [[x]]\nramas2 (N x as) = concat (map (map (x:)) (map ramas2 as))\n\n-- 3\u00aa soluci\u00f3n\nramas3 :: Arbol b -> [[b]]\nramas3 (N x []) = [[x]]\nramas3 (N x as) = concat (map (map (x:) . ramas3) as)\n\n-- 4\u00aa soluci\u00f3n\nramas4 :: Arbol b -> [[b]]\nramas4 (N x []) = [[x]]\nramas4 (N x as) = concatMap (map (x:) . ramas4) as\n\n-- 5\u00aa soluci\u00f3n\nramas5 :: Arbol a -> [[a]]\nramas5 (N x []) = [[x]]\nramas5 (N x xs) = map ramas5 xs >>= map (x:)\n\n-- Comprobaci\u00f3n de la equivalencia de las definiciones\n-- ===================================================\n\n-- (arbolArbitrario n) es un \u00e1rbol aleatorio de orden n. Por ejemplo,\n--    \u03bb> sample (arbolArbitrario 4 :: Gen (Arbol Int))\n--    N 0 [N 0 []]\n--    N 1 [N 1 [N (-2) [N (-1) [N (-1) [N (-1) [N 1 []]]]]],N (-1) [N 2 []]]\n--    N 1 [N (-2) [],N 0 [N (-4) [N (-2) []]]]\n--    N (-4) [N 1 [],N 0 [N 6 [N (-4) []],N 2 [N 3 []]]]\n--    N (-7) [N (-7) [N (-3) []]]\n--    N (-2) [N (-8) []]\n--    N (-3) [N 3 [N 2 []]]\n--    N (-12) [N 5 [],N 0 []]\n--    N 14 [N 13 [N (-12) []],N 11 [],N 8 [N (-13) []]]\n--    N (-12) [N (-6) [N 16 [N (-14) [N (-1) []]]]]\n--    N (-5) []\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_arbol :: Arbol Int -> Bool\nprop_arbol a =\n  all (== ramas1 a)\n      [ramas2 a,\n       ramas3 a,\n       ramas4 a,\n       ramas5 a]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_arbol\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> ej600 <- generate (arbolArbitrario 600 :: Gen (Arbol Int))\n--    \u03bb> length (ramas1 ej600)\n--    1262732\n--    (1.92 secs, 1,700,238,488 bytes)\n--    \u03bb> length (ramas2 ej600)\n--    1262732\n--    (1.94 secs, 2,549,877,280 bytes)\n--    \u03bb> length (ramas3 ej600)\n--    1262732\n--    (1.99 secs, 2,446,508,472 bytes)\n--    \u03bb> length (ramas4 ej600)\n--    1262732\n--    (1.67 secs, 2,090,469,104 bytes)\n--    \u03bb> length (ramas5 ej600)\n--    1262732\n--    (1.66 secs, 2,112,198,232 bytes)\n<\/pre>\n<p>La elaboraci\u00f3n de las soluciones se encuentran en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/Bj0jTH77k2k\" 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. Alfabeto comenzando en un car\u00e1cter<\/h3>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- Definir la funci\u00f3n\n--    alfabetoDesde :: Char -> String\n-- tal que (alfabetoDesde c) es el alfabeto, en min\u00fascula, comenzando en\n-- el car\u00e1cter c, si c es una letra min\u00fascula y comenzando en 'a', en\n-- caso contrario. Por ejemplo,\n--    alfabetoDesde 'e'  ==  \"efghijklmnopqrstuvwxyzabcd\"\n--    alfabetoDesde 'a'  ==  \"abcdefghijklmnopqrstuvwxyz\"\n--    alfabetoDesde '7'  ==  \"abcdefghijklmnopqrstuvwxyz\"\n--    alfabetoDesde '{'  ==  \"abcdefghijklmnopqrstuvwxyz\"\n--    alfabetoDesde 'B'  ==  \"abcdefghijklmnopqrstuvwxyz\"\n-- ---------------------------------------------------------------------\n\nimport Data.Char (isLower, isAscii)\nimport Test.QuickCheck\n\n-- 1\u00aa soluci\u00f3n\nalfabetoDesde1 :: Char -> String\nalfabetoDesde1 c =\n  dropWhile (<c) ['a'..'z'] ++ takeWhile (<c) ['a'..'z']\n\n-- 2\u00aa soluci\u00f3n\nalfabetoDesde2 :: Char -> String\nalfabetoDesde2 c = ys ++ xs\n  where (xs,ys) = span (<c) ['a'..'z']\n\n-- 3\u00aa soluci\u00f3n\nalfabetoDesde3 :: Char -> String\nalfabetoDesde3 c = ys ++ xs\n  where (xs,ys) = break (==c) ['a'..'z']\n\n-- 4\u00aa soluci\u00f3n\nalfabetoDesde4 :: Char -> String\nalfabetoDesde4 c\n  | 'a' <= c &#038;&#038; c <= 'z' = [c..'z'] ++ ['a'..pred c]\n  | otherwise            = ['a'..'z']\n\n-- 5\u00aa soluci\u00f3n\nalfabetoDesde5 :: Char -> String\nalfabetoDesde5 c\n  | isLower c = [c..'z'] ++ ['a'..pred c]\n  | otherwise = ['a'..'z']\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- La propiedad es\nprop_alfabetoDesde :: Property\nprop_alfabetoDesde =\n  forAll (arbitrary `suchThat` isAscii) $ \\c ->\n  all (== alfabetoDesde1 c)\n      [f c | f <- [alfabetoDesde2,\n                   alfabetoDesde3,\n                   alfabetoDesde4,\n                   alfabetoDesde5]]\n\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_alfabetoDesde\n--    +++ OK, passed 100 tests.\n<\/pre>\n<p>La elaboraci\u00f3n de las soluciones se encuentran en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/4eBJi5_8qM0\" 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. Numeraci\u00f3n de las ternas de n\u00fameros naturales.<\/h3>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- Las ternas de n\u00fameros naturales se pueden ordenar como sigue\n--    (0,0,0),\n--    (0,0,1),(0,1,0),(1,0,0),\n--    (0,0,2),(0,1,1),(0,2,0),(1,0,1),(1,1,0),(2,0,0),\n--    (0,0,3),(0,1,2),(0,2,1),(0,3,0),(1,0,2),(1,1,1),(1,2,0),(2,0,1),...\n--    ...\n--\n-- Definir la funci\u00f3n\n--    posicion :: (Int,Int,Int) -> Int\n-- tal que (posicion (x,y,z)) es la posici\u00f3n de la terna de n\u00fameros\n-- naturales (x,y,z) en la ordenaci\u00f3n anterior. Por ejemplo,\n--    posicion (0,1,0)  ==  2\n--    posicion (0,0,2)  ==  4\n--    posicion (0,1,1)  ==  5\n--\n-- Comprobar con QuickCheck que\n-- + la posici\u00f3n de (x,0,0) es x(x\u00b2+6x+11)\/6\n-- + la posici\u00f3n de (0,y,0) es y(y\u00b2+3y+ 8)\/6\n-- + la posici\u00f3n de (0,0,z) es z(z\u00b2+3z+ 2)\/6\n-- + la posici\u00f3n de (x,x,x) es x(9x\u00b2+14x+7)\/2\n-- ---------------------------------------------------------------------\n\nimport Data.List (elemIndex)\nimport Data.Maybe (fromJust)\nimport Test.QuickCheck\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nposicion1 :: (Int,Int,Int) -> Int\nposicion1 t = aux 0 ternas\n  where aux n (t':ts) | t' == t   = n\n                      | otherwise = aux (n+1) ts\n\n-- ternas es la lista ordenada de las ternas de n\u00fameros naturales. Por ejemplo,\n--    \u03bb> take 9 ternas\n--    [(0,0,0),(0,0,1),(0,1,0),(1,0,0),(0,0,2),(0,1,1),(0,2,0),(1,0,1),(1,1,0)]\nternas :: [(Int,Int,Int)]\nternas = [(x,y,n-x-y) | n <- [0..], x <- [0..n], y <- [0..n-x]]\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nposicion2 :: (Int,Int,Int) -> Int\nposicion2 t =\n  head [n | (n,t') <- zip [0..] ternas, t' == t]\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nposicion3 :: (Int,Int,Int) -> Int\nposicion3 t = indice t ternas\n\n-- (indice x ys) es el \u00edndice de x en ys. Por ejemplo,\n--    indice 5 [0..]  ==  5\nindice :: Eq a => a -> [a] -> Int\nindice x ys = length (takeWhile (\/= x) ys)\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\nposicion4 :: (Int,Int,Int) -> Int\nposicion4 t = fromJust (elemIndex t ternas)\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nposicion5 :: (Int,Int,Int) -> Int\nposicion5 = fromJust . (`elemIndex` ternas)\n\n-- Equivalencia\n-- ============\n\n-- La propiedad es\nprop_posicion_equiv :: NonNegative Int\n                    -> NonNegative Int\n                    -> NonNegative Int\n                    -> Bool\nprop_posicion_equiv (NonNegative x) (NonNegative y) (NonNegative z) =\n  all (== posicion1 (x,y,z))\n      [f (x,y,z) | f <- [ posicion2\n                        , posicion3\n                        , posicion4\n                        , posicion5 ]]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheckWith (stdArgs {maxSize=20}) prop_posicion_equiv\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> posicion1 (147,46,116)\n--    5000000\n--    (5.84 secs, 2,621,428,184 bytes)\n--    \u03bb> posicion2 (147,46,116)\n--    5000000\n--    (3.63 secs, 2,173,230,200 bytes)\n--    \u03bb> posicion3 (147,46,116)\n--    5000000\n--    (2.48 secs, 1,453,229,880 bytes)\n--    \u03bb> posicion4 (147,46,116)\n--    5000000\n--    (1.91 secs, 1,173,229,840 bytes)\n--    \u03bb> posicion5 (147,46,116)\n--    5000000\n--    (1.94 secs, 1,173,229,960 bytes)\n\n-- En lo que sigue, usaremos la 5\u00aa definici\u00f3n\nposicion :: (Int,Int,Int) -> Int\nposicion = posicion5\n\n-- Propiedades\n-- ===========\n\n-- La 1\u00aa propiedad es\nprop_posicion1 :: NonNegative Int -> Bool\nprop_posicion1 (NonNegative x) =\n  posicion (x,0,0) == x * (x^2 + 6*x + 11) `div` 6\n\n-- Su comprobaci\u00f3n es\n--    \u03bb> quickCheckWith (stdArgs {maxSize=20}) prop_posicion1\n--    +++ OK, passed 100 tests.\n\n-- La 2\u00aa propiedad es\nprop_posicion2 :: NonNegative Int -> Bool\nprop_posicion2 (NonNegative y) =\n  posicion (0,y,0) == y * (y^2 + 3*y + 8) `div` 6\n\n-- Su comprobaci\u00f3n es\n--    \u03bb> quickCheckWith (stdArgs {maxSize=20}) prop_posicion2\n--    +++ OK, passed 100 tests.\n\n-- La 3\u00aa propiedad es\nprop_posicion3 :: NonNegative Int -> Bool\nprop_posicion3 (NonNegative z) =\n  posicion (0,0,z) == z * (z^2 + 3*z + 2) `div` 6\n\n-- Su comprobaci\u00f3n es\n--    \u03bb> quickCheckWith (stdArgs {maxSize=20}) prop_posicion3\n--    +++ OK, passed 100 tests.\n\n-- La 4\u00aa propiedad es\nprop_posicion4 :: NonNegative Int -> Bool\nprop_posicion4 (NonNegative x) =\n  posicion (x,x,x) == x * (9 * x^2 + 14 * x + 7) `div` 2\n\n-- Su comprobaci\u00f3n es\n--    \u03bb> quickCheckWith (stdArgs {maxSize=20}) prop_posicion4\n--    +++ OK, passed 100 tests.\n<\/pre>\n<p>La elaboraci\u00f3n de las soluciones se encuentran en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/3pbmjjozB6g\" 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. Ordenaci\u00f3n de estructuras<\/h3>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- Las notas de los dos primeros ex\u00e1menes se pueden representar mediante\n-- el siguiente tipo de dato\n--    data Notas = Notas String Int Int\n--      deriving (Read, Show, Eq)\n-- Por ejemplo, (Notas \"Juan\" 6 5) representar las notas de un alumno\n-- cuyo nombre es Juan, la nota del primer examen es 6 y la del segundo\n-- es 5.\n--\n-- Definir la funci\u00f3n\n--    ordenadas :: [Notas] -> [Notas]\n-- tal que (ordenadas ns) es la lista de las notas ns ordenadas\n-- considerando primero la nota del examen 2, a continuaci\u00f3n la del\n-- examen 1 y finalmente el nombre. Por ejemplo,\n--    \u03bb> ordenadas [Notas \"Juan\" 6 5, Notas \"Luis\" 3 7]\n--    [Notas \"Juan\" 6 5,Notas \"Luis\" 3 7]\n--    \u03bb> ordenadas [Notas \"Juan\" 6 5, Notas \"Luis\" 3 4]\n--    [Notas \"Luis\" 3 4,Notas \"Juan\" 6 5]\n--    \u03bb> ordenadas [Notas \"Juan\" 6 5, Notas \"Luis\" 7 4]\n--    [Notas \"Luis\" 7 4,Notas \"Juan\" 6 5]\n--    \u03bb> ordenadas [Notas \"Juan\" 6 4, Notas \"Luis\" 7 4]\n--    [Notas \"Juan\" 6 4,Notas \"Luis\" 7 4]\n--    \u03bb> ordenadas [Notas \"Juan\" 6 4, Notas \"Luis\" 5 4]\n--    [Notas \"Luis\" 5 4,Notas \"Juan\" 6 4]\n--    \u03bb> ordenadas [Notas \"Juan\" 5 4, Notas \"Luis\" 5 4]\n--    [Notas \"Juan\" 5 4,Notas \"Luis\" 5 4]\n--    \u03bb> ordenadas [Notas \"Juan\" 5 4, Notas \"Eva\" 5 4]\n--    [Notas \"Eva\" 5 4,Notas \"Juan\" 5 4]\n-- ---------------------------------------------------------------------\n\nimport Data.List (sort, sortBy)\nimport Test.QuickCheck\n\ndata Notas = Notas String Int Int\n  deriving (Read, Show, Eq)\n\n-- 1\u00aa soluci\u00f3n\nordenadas1 :: [Notas] -> [Notas]\nordenadas1 ns =\n  [Notas n x y | (y,x,n) <- sort [(y1,x1,n1) | (Notas n1 x1 y1) <- ns]]\n\n-- 2\u00aa soluci\u00f3n\nordenadas2 :: [Notas] -> [Notas]\nordenadas2 ns =\n  map (\\(y,x,n) -> Notas n x y) (sort [(y1,x1,n1) | (Notas n1 x1 y1) <- ns])\n\n-- 3\u00aa soluci\u00f3n\nordenadas3 :: [Notas] -> [Notas]\nordenadas3 ns = sortBy (\\(Notas n1 x1 y1) (Notas n2 x2 y2) ->\n                          compare (y1,x1,n1) (y2,x2,n2))\n                       ns\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\ninstance Ord Notas where\n  Notas n1 x1 y1 <= Notas n2 x2 y2 = (y1,x1,n1) <= (y2,x2,n2)\n\nordenadas4 :: [Notas] -> [Notas]\nordenadas4 = sort\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- notasArbitraria es un generador aleatorio de notas. Por ejemplo,\n--    \u03bb> sample notasArbitraria\n--    Notas \"achjkqruvxy\" 3 3\n--    Notas \"abfgikmptuvy\" 10 10\n--    Notas \"degjmptvwx\" 7 9\n--    Notas \"cdefghjmnoqrsuw\" 0 9\n--    Notas \"bcdfikmstuxz\" 1 8\n--    Notas \"abcdhkopqsvwx\" 10 7\n--    Notas \"abghiklnoqstvwx\" 0 0\n--    Notas \"abfghklmnoptuvx\" 4 9\n--    Notas \"bdehjkmpqsxyz\" 0 4\n--    Notas \"afghijmopsvwz\" 3 7\n--    Notas \"bdefghjklnoqx\" 2 3\nnotasArbitraria :: Gen Notas\nnotasArbitraria = do\n  n <- sublistOf ['a'..'z']\n  x <- chooseInt (0, 10)\n  y <- chooseInt (0, 10)\n  return (Notas n x y)\n\n-- Notas es una subclase de Arbitrary\ninstance Arbitrary Notas where\n  arbitrary = notasArbitraria\n\n-- La propiedad es\nprop_ordenadas :: [Notas] -> Bool\nprop_ordenadas ns =\n  all (== ordenadas1 ns)\n      [f ns | f <- [ordenadas2,\n                    ordenadas3,\n                    ordenadas4]]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_ordenadas\n--    +++ OK, passed 100 tests.\n<\/pre>\n<p>La elaboraci\u00f3n de las soluciones se encuentran en el siguiente v\u00eddeo<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/mlgDbAPStdM\" 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. Valores de polinomios representados con vectores. 2. Ramas de un \u00e1rbol 3. Alfabeto comenzando en un car\u00e1cter 4. Numeraci\u00f3n de las ternas de n\u00fameros naturales. 5. Ordenaci\u00f3n de estructuras 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\/7693"}],"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=7693"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7693\/revisions"}],"predecessor-version":[{"id":7694,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7693\/revisions\/7694"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=7693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=7693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=7693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}