{"id":7926,"date":"2023-04-22T13:19:21","date_gmt":"2023-04-22T11:19:21","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=7926"},"modified":"2023-04-22T13:19:21","modified_gmt":"2023-04-22T11:19:21","slug":"22-abr-23","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/22-abr-23\/","title":{"rendered":"La semana en Exercitium (22 de abril de 2023)"},"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. El tipo abstracto de datos de los polinomios<\/a><\/li>\n<li><a href=\"#ej2\">2. Transformaciones entre las representaciones dispersa y densa de polinomios<\/a><\/li>\n<li><a href=\"#ej3\">3. Transformaciones entre polinomios y listas dispersas<\/a><\/li>\n<li><a href=\"#ej4\">4. Coeficiente del t\u00e9rmino de grado k de un polinomio<\/a><\/li>\n<li><a href=\"#ej5\">5. Transformaciones entre polinomios y listas densas<\/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. El tipo abstracto de datos de los polinomios<\/h3>\n<h3>1. El tipo abstracto de datos de los polinomios<\/h3>\n<p>Un polinomio es una expresi\u00f3n matem\u00e1tica compuesta por una suma de t\u00e9rminos, donde cada t\u00e9rmino es el producto de un coeficiente y una variable elevada a una potencia. Por ejemplo, el polinomio 3x^2+2x-1 tiene un t\u00e9rmino de segundo grado (3x^2), un t\u00e9rmino de primer grado (2x) y un t\u00e9rmino constante (-1).<\/p>\n<p>Las operaciones que definen al tipo abstracto de datos (TAD) de los polinomios (cuyos coeficientes son del tipo a) son las siguientes:<\/p>\n<pre lang=\"text\">\n   polCero   :: Polinomio a\n   esPolCero :: Polinomio a -> Bool\n   consPol   :: (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a\n   grado     :: Polinomio a -> Int\n   coefLider :: Num a => Polinomio a -> a\n   restoPol  :: (Num a, Eq a) => Polinomio a -> Polinomio a\n<\/pre>\n<p>tales que<\/p>\n<ul>\n<li>polCero es el polinomio cero.<\/li>\n<li>(esPolCero p) se verifica si p es el polinomio cero.<\/li>\n<li>(consPol n b p) es el polinomio bx^n+p<\/li>\n<li>(grado p) es el grado del polinomio p.<\/li>\n<li>(coefLider p) es el coeficiente l\u00edder del polinomio p.<\/li>\n<li>(restoPol p) es el resto del polinomio p.<\/li>\n<\/ul>\n<p>Por ejemplo, el polinomio<\/p>\n<pre lang=\"text\">\n   3*x^4 + -5*x^2 + 3\n<\/pre>\n<p>se representa por<\/p>\n<pre lang=\"text\">\n   consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\n<\/pre>\n<p>Las operaciones tienen que verificar las siguientes propiedades:<\/p>\n<ul>\n<li>esPolCero polCero<\/li>\n<li>n > grado p &amp;&amp; b \/= 0 ==> not (esPolCero (consPol n b p))<\/li>\n<li>consPol (grado p) (coefLider p) (restoPol p) == p<\/li>\n<li>n > grado p &amp;&amp; b \/= 0 ==> grado (consPol n b p) == n<\/li>\n<li>n > grado p &amp;&amp; b \/= 0 ==> coefLider (consPol n b p) == b<\/li>\n<li>n > grado p &amp;&amp; b \/= 0 ==> restoPol (consPol n b p) == p<\/li>\n<\/ul>\n<h3>2. Los polinomios en Haskell<\/h3>\n<h4>2.1. El tipo abstracto de datos de los polinomios en Haskell<\/h4>\n<p>El TAD de los polinomios se encuentra en el m\u00f3dulo <a href=\"https:\/\/bit.ly\/3MRpRth\">Polinomio.hs<\/a> cuyo contenido es el siguiente:<\/p>\n<pre lang=\"haskell\">\nmodule TAD.Polinomio\n  ( Polinomio,\n    polCero,   -- Polinomio a\n    esPolCero, -- Polinomio a -> Bool\n    consPol,   -- (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a\n    grado,     -- Polinomio a -> Int\n    coefLider, -- Num a => Polinomio a -> a\n    restoPol   -- (Num a, Eq a) => Polinomio a -> Polinomio a\n  ) where\n\nimport TAD.PolRepTDA\n-- import TAD.PolRepDensa\n-- import TAD.PolRepDispersa\n<\/pre>\n<p>Para usar el TAD hay que usar una implementaci\u00f3n concreta. En principio, consideraremos las siguientes:<\/p>\n<ul>\n<li>mediante tipo de dato algebraico,<\/li>\n<li>mediante listas densas y<\/li>\n<li>mediante listas dispersas.<\/li>\n<\/ul>\n<p>Hay que elegir la que se desee utilizar, descoment\u00e1ndola y comentando las otras.<\/p>\n<h4>2.2. Implementaci\u00f3n de los polinomios mediante tipos de datos algebraicos<\/h4>\n<p>Representamos un polinomio mediante los constructores ConsPol y<br \/>\nPolCero. Por ejemplo, el polinomio<\/p>\n<pre lang=\"text\">\n   6x^4 -5x^2 + 4x -7\n<\/pre>\n<p>se representa por<\/p>\n<pre lang=\"text\">\n   ConsPol 4 6 (ConsPol 2 (-5) (ConsPol 1 4 (ConsPol 0 (-7) PolCero)))\n<\/pre>\n<p>La implementaci\u00f3n se encuentra en el m\u00f3dulo <a href=\"https:\/\/bit.ly\/3zPN8Ec\">PolRepTDA.hs<\/a> cuyo contenido es el siguiente:<\/p>\n<pre lang=\"haskell\">\n{-# LANGUAGE TemplateHaskell #-}\n{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}\n\nmodule TAD.PolRepTDA\n  ( Polinomio,\n    polCero,   -- Polinomio a\n    esPolCero, -- Polinomio a -> Bool\n    consPol,   -- (Num a, Eq a)) => Int -> a -> Polinomio a -> Polinomio a\n    grado,     -- Polinomio a -> Int\n    coefLider, -- Num t => Polinomio t -> t\n    restoPol   -- Polinomio t -> Polinomio t\n  ) where\n\nimport Test.QuickCheck\n\n-- Polinomio como tipo de dato algebra\ndata Polinomio a = PolCero\n                 | ConsPol Int a (Polinomio a)\n  deriving Eq\n\n-- (escribePol p) es la cadena correspondiente al polinomio p. Por\n-- ejemplo,\n--    \u03bb> escribePol (consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero)))\n--    \"3*x^4 + -5*x^2 + 3\"\nescribePol :: (Num a, Show a, Eq a) => Polinomio a -> String\nescribePol PolCero               = \"0\"\nescribePol (ConsPol 0 b PolCero) = show b\nescribePol (ConsPol 0 b p)       = concat [show b, \" + \", escribePol p]\nescribePol (ConsPol 1 b PolCero) = show b ++ \"*x\"\nescribePol (ConsPol 1 b p)       = concat [show b, \"*x + \", escribePol p]\nescribePol (ConsPol n 1 PolCero) = \"x^\" ++ show n\nescribePol (ConsPol n b PolCero) = concat [show b, \"*x^\", show n]\nescribePol (ConsPol n 1 p)       = concat [\"x^\", show n, \" + \", escribePol p]\nescribePol (ConsPol n b p)       = concat [show b, \"*x^\", show n, \" + \", escribePol p]\n\n-- Procedimiento de escritura de polinomios.\ninstance (Num a, Show a, Eq a) => Show (Polinomio a) where\n  show = escribePol\n\n-- Ejemplos de polinomios con coeficientes enteros:\nejPol1, ejPol2, ejPol3 :: Polinomio Int\nejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\nejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\nejPol3 = consPol 4 6 (consPol 1 2 polCero)\n\n-- Comprobaci\u00f3n de escritura:\n--    > ejPol1\n--    3*x^4 + -5*x^2 + 3\n--    > ejPol2\n--    x^5 + 5*x^2 + 4*x\n--    > ejPol3\n--    6*x^4 + 2*x\n\n-- polCero es el polinomio cero. Por ejemplo,\n--    > polCero\n--    0\npolCero :: Polinomio a\npolCero = PolCero\n\n-- (esPolCero p) se verifica si p es el polinomio cero. Por ejemplo,\n--    esPolCero polCero  ==  True\n--    esPolCero ejPol1   ==  False\nesPolCero :: Polinomio a -> Bool\nesPolCero PolCero = True\nesPolCero _       = False\n\n-- (consPol n b p) es el polinomio bx^n+p. Por ejemplo,\n--    ejPol2               ==  x^5 + 5*x^2 + 4*x\n--    consPol 3 0 ejPol2   ==  x^5 + 5*x^2 + 4*x\n--    consPol 3 2 polCero  ==  2*x^3\n--    consPol 6 7 ejPol2   ==  7*x^6 + x^5 + 5*x^2 + 4*x\n--    consPol 4 7 ejPol2   ==  x^5 + 7*x^4 + 5*x^2 + 4*x\n--    consPol 5 7 ejPol2   ==  8*x^5 + 5*x^2 + 4*x\nconsPol :: (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a\nconsPol _ 0 p = p\nconsPol n b PolCero = ConsPol n b PolCero\nconsPol n b (ConsPol m c p)\n  | n > m      = ConsPol n b (ConsPol m c p)\n  | n < m      = ConsPol m c (consPol n b p)\n  | b+c == 0   = p\n  | otherwise  = ConsPol n (b+c) p\n\n-- (grado p) es el grado del polinomio p. Por ejemplo,\n--    ejPol3        ==  6*x^4 + 2*x\n--    grado ejPol3  ==  4\ngrado :: Polinomio a -> Int\ngrado PolCero         = 0\ngrado (ConsPol n _ _) = n\n\n-- (coefLider p) es el coeficiente l\u00edder del polinomio p. Por ejemplo,\n--    ejPol3            ==  6*x^4 + 2*x\n--    coefLider ejPol3  ==  6\ncoefLider :: Num t => Polinomio t -> t\ncoefLider PolCero         = 0\ncoefLider (ConsPol _ b _) = b\n\n-- (restoPol p) es el resto del polinomio p. Por ejemplo,\n--    ejPol3           ==  6*x^4 + 2*x\n--    restoPol ejPol3  ==  2*x\n--    ejPol2           ==  x^5 + 5*x^2 + 4*x\n--    restoPol ejPol2  ==  5*x^2 + 4*x\nrestoPol :: Polinomio t -> Polinomio t\nrestoPol PolCero         = PolCero\nrestoPol (ConsPol _ _ p) = p\n\n-- Generador de polinomios                                          --\n-- =======================\n\n-- genPolinomio es un generador de polinomios. Por ejemplo,\n--    \u03bb> sample (genPol 1)\n--    7*x^9 + 9*x^8 + 10*x^7 + -14*x^5 + -15*x^2 + -10\n--    -4*x^8 + 2*x\n--    -8*x^9 + 4*x^8 + 2*x^6 + 4*x^5 + -6*x^4 + 5*x^2 + -8*x\n--    -9*x^9 + x^5 + -7\n--    8*x^10 + -9*x^7 + 7*x^6 + 9*x^5 + 10*x^3 + -1*x^2\n--    7*x^10 + 5*x^9 + -5\n--    -8*x^10 + -7\n--    -5*x\n--    5*x^10 + 4*x^4 + -3\n--    3*x^3 + -4\n--    10*x\ngenPol :: (Num a, Arbitrary a, Eq a) => Int -> Gen (Polinomio a)\ngenPol 0 = return polCero\ngenPol _ = do\n  n <- choose (0,10)\n  b <- arbitrary\n  p <- genPol (div n 2)\n  return (consPol n b p)\n\ninstance (Num a, Arbitrary a, Eq a) => Arbitrary (Polinomio a) where\n  arbitrary = sized genPol\n\n-- Propiedades de los polinomios\n-- =============================\n\n-- polCero es el polinomio cero.\nprop_polCero_es_cero :: Bool\nprop_polCero_es_cero =\n  esPolCero polCero\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- (consPol n b p) es un polinomio distinto del cero.\nprop_consPol_no_cero :: Int -> Int -> Polinomio Int -> Property\nprop_consPol_no_cero n b p =\n  n > grado p && b \/= 0  ==>\n  not (esPolCero (consPol n b p))\n\n-- (consPol (grado p) (coefLider p) (restoPol p)) es igual a p.\nprop_consPol :: Polinomio Int -> Bool\nprop_consPol p =\n  consPol (grado p) (coefLider p) (restoPol p) == p\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el grado de (consPol n b p) es n.\nprop_grado :: Int -> Int -> Polinomio Int -> Property\nprop_grado n b p =\n  n > grado p && b \/= 0 ==>\n  grado (consPol n b p) == n\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el coeficiente l\u00edder de (consPol n b p) es b.\nprop_coefLider :: Int -> Int -> Polinomio Int -> Property\nprop_coefLider n b p =\n  n > grado p && b \/= 0 ==>\n  coefLider (consPol n b p) == b\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el resto de (consPol n b p) es p.\nprop_restoPol :: Int -> Int -> Polinomio Int -> Property\nprop_restoPol n b p =\n  n > grado p && b \/= 0 ==>\n  restoPol (consPol n b p) == p\n\n-- Verificaci\u00f3n\n-- ============\n\nreturn []\n\nverificaPol :: IO Bool\nverificaPol = $quickCheckAll\n\n-- La verificaci\u00f3n es\n--    \u03bb> verificaPol\n--    === prop_polCero_es_cero from PolPropiedades.hs:53 ===\n--    +++ OK, passed 1 test.\n--\n--    === prop_consPol_no_cero from PolPropiedades.hs:63 ===\n--    +++ OK, passed 100 tests; 251 discarded.\n--\n--    === prop_consPol from PolPropiedades.hs:73 ===\n--    +++ OK, passed 100 tests.\n--\n--    === prop_grado from PolPropiedades.hs:83 ===\n--    +++ OK, passed 100 tests; 321 discarded.\n--\n--    === prop_coefLider from PolPropiedades.hs:94 ===\n--    +++ OK, passed 100 tests; 340 discarded.\n--\n--    === prop_restoPol from PolPropiedades.hs:105 ===\n--    +++ OK, passed 100 tests; 268 discarded.\n--\n--    True\n<\/pre>\n<h4>2.3. Implementaci\u00f3n de polinomios mediante listas densas<\/h4>\n<p>Representaremos un polinomio por la lista de sus coeficientes ordenados en orden decreciente seg\u00fan el grado. Por ejemplo, el polinomio<\/p>\n<pre lang=\"text\">\n   6x^4 -5x^2 + 4x -7\n<\/pre>\n<p>se representa por<\/p>\n<pre lang=\"text\">\n   [6,0,-2,4,-7]\n<\/pre>\n<p>En la representaci\u00f3n se supone que, si la lista no es vac\u00eda, su primer elemento es distinto de cero.<\/p>\n<p>La implementaci\u00f3n se encuentra en el m\u00f3dulo <a href=\"https:\/\/bit.ly\/3GBR4Ml\">PolRepDensa.hs<\/a> cuyo contenido es el siguiente:<\/p>\n<pre lang=\"haskell\">\n{-# LANGUAGE TemplateHaskell #-}\n{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}\n\nmodule TAD.PolRepDensa\n  ( Polinomio,\n    polCero,   -- Polinomio a\n    esPolCero, -- Polinomio a -> Bool\n    consPol,   -- (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a\n    grado,     -- Polinomio a -> Int\n    coefLider, -- Num a => Polinomio a -> a\n    restoPol   -- (Num a, Eq a) => Polinomio a -> Polinomio a\n  ) where\n\nimport Test.QuickCheck\n\nnewtype Polinomio a = Pol [a]\n  deriving Eq\n\n-- (escribePol p) es la cadena correspondiente al polinomio p. Por\n-- ejemplo,\n--    \u03bb> escribePol (consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero)))\n--    \"3*x^4 + -5*x^2 + 3\"\nescribePol :: (Num a, Show a, Eq a) => Polinomio a -> String\nescribePol pol\n  | esPolCero pol         = \"0\"\n  | n == 0 && esPolCero p = show a\n  | n == 0                = concat [show a, \" + \", escribePol p]\n  | n == 1 && esPolCero p = show a ++ \"*x\"\n  | n == 1                = concat [show a, \"*x + \", escribePol p]\n  | a == 1 && esPolCero p = \"x^\" ++ show n\n  | esPolCero p           = concat [show a, \"*x^\", show n]\n  | a == 1                = concat [\"x^\", show n, \" + \", escribePol p]\n  | otherwise             = concat [show a, \"*x^\", show n, \" + \", escribePol p]\n  where n = grado pol\n        a = coefLider pol\n        p = restoPol pol\n\n-- Procedimiento de escritura de polinomios.\ninstance (Num a, Show a, Eq a) => Show (Polinomio a) where\n  show = escribePol\n\n-- Ejemplos de polinomios con coeficientes enteros:\nejPol1, ejPol2, ejPol3 :: Polinomio Int\nejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\nejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\nejPol3 = consPol 4 6 (consPol 1 2 polCero)\n\n-- Comprobaci\u00f3n de escritura:\n--    > ejPol1\n--    3*x^4 + -5*x^2 + 3\n--    > ejPol2\n--    x^5 + 5*x^2 + 4*x\n--    > ejPol3\n--    6*x^4 + 2*x\n\n-- polCero es el polinomio cero. Por ejemplo,\n--    \u03bb> polCero\n--    0\npolCero :: Polinomio a\npolCero = Pol []\n\n-- (esPolCero p) se verifica si p es el polinomio cero. Por ejemplo,\n--    esPolCero polCero  ==  True\n--    esPolCero ejPol1   ==  False\nesPolCero :: Polinomio a -> Bool\nesPolCero (Pol []) = True\nesPolCero _        = False\n\n-- (consPol n b p) es el polinomio bx^n+p. Por ejemplo,\n--    ejPol2               ==  x^5 + 5*x^2 + 4*x\n--    consPol 3 0 ejPol2   ==  x^5 + 5*x^2 + 4*x\n--    consPol 3 2 polCero  ==  2*x^3\n--    consPol 6 7 ejPol2   ==  7*x^6 + x^5 + 5*x^2 + 4*x\n--    consPol 4 7 ejPol2   ==  x^5 + 7*x^4 + 5*x^2 + 4*x\n--    consPol 5 7 ejPol2   ==  8*x^5 + 5*x^2 + 4*x\nconsPol :: (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a\nconsPol _ 0 p = p\nconsPol n b p@(Pol xs)\n    | esPolCero p = Pol (b : replicate n 0)\n    | n > m       = Pol (b : replicate (n-m-1) 0 ++ xs)\n    | n < m       = consPol m c (consPol n b (restoPol p))\n    | b+c == 0    = Pol (dropWhile (==0) (tail xs))\n    | otherwise   = Pol ((b+c):tail xs)\n    where\n      c = coefLider p\n      m = grado p\n\n-- (grado p) es el grado del polinomio p. Por ejemplo,\n--    ejPol3        ==  6*x^4 + 2*x\n--    grado ejPol3  ==  4\ngrado :: Polinomio a -> Int\ngrado (Pol []) = 0\ngrado (Pol xs) = length xs - 1\n\n-- (coefLider p) es el coeficiente l\u00edder del polinomio p. Por ejemplo,\n--    ejPol3            ==  6*x^4 + 2*x\n--    coefLider ejPol3  ==  6\ncoefLider :: Num t => Polinomio t -> t\ncoefLider (Pol [])    = 0\ncoefLider (Pol (a:_)) = a\n\n-- (restoPol p) es el resto del polinomio p. Por ejemplo,\n--    ejPol3           ==  6*x^4 + 2*x\n--    restoPol ejPol3  ==  2*x\n--    ejPol2           ==  x^5 + 5*x^2 + 4*x\n--    restoPol ejPol2  ==  5*x^2 + 4*x\nrestoPol :: (Num t, Eq t) => Polinomio t -> Polinomio t\nrestoPol (Pol [])     = polCero\nrestoPol (Pol [_])    = polCero\nrestoPol (Pol (_:b:as))\n  | b == 0    = Pol (dropWhile (==0) as)\n  | otherwise = Pol (b:as)\n\n-- Generador de polinomios\n-- =======================\n\n-- genPolinomio es un generador de polinomios. Por ejemplo,\n--    \u03bb> sample (genPol 1)\n--    7*x^9 + 9*x^8 + 10*x^7 + -14*x^5 + -15*x^2 + -10\n--    -4*x^8 + 2*x\n--    -8*x^9 + 4*x^8 + 2*x^6 + 4*x^5 + -6*x^4 + 5*x^2 + -8*x\n--    -9*x^9 + x^5 + -7\n--    8*x^10 + -9*x^7 + 7*x^6 + 9*x^5 + 10*x^3 + -1*x^2\n--    7*x^10 + 5*x^9 + -5\n--    -8*x^10 + -7\n--    -5*x\n--    5*x^10 + 4*x^4 + -3\n--    3*x^3 + -4\n--    10*x\ngenPol :: (Num a, Arbitrary a, Eq a) => Int -> Gen (Polinomio a)\ngenPol 0 = return polCero\ngenPol _ = do\n  n <- choose (0,10)\n  b <- arbitrary\n  p <- genPol (div n 2)\n  return (consPol n b p)\n\ninstance (Num a, Arbitrary a, Eq a) => Arbitrary (Polinomio a) where\n  arbitrary = sized genPol\n\n-- Propiedades de los polinomios\n-- =============================\n\n-- polCero es el polinomio cero.\nprop_polCero_es_cero :: Bool\nprop_polCero_es_cero =\n  esPolCero polCero\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- (consPol n b p) es un polinomio distinto del cero.\nprop_consPol_no_cero :: Int -> Int -> Polinomio Int -> Property\nprop_consPol_no_cero n b p =\n  n > grado p && b \/= 0  ==>\n  not (esPolCero (consPol n b p))\n\n-- (consPol (grado p) (coefLider p) (restoPol p)) es igual a p.\nprop_consPol :: Polinomio Int -> Bool\nprop_consPol p =\n  consPol (grado p) (coefLider p) (restoPol p) == p\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el grado de (consPol n b p) es n.\nprop_grado :: Int -> Int -> Polinomio Int -> Property\nprop_grado n b p =\n  n > grado p && b \/= 0 ==>\n  grado (consPol n b p) == n\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el coeficiente l\u00edder de (consPol n b p) es b.\nprop_coefLider :: Int -> Int -> Polinomio Int -> Property\nprop_coefLider n b p =\n  n > grado p && b \/= 0 ==>\n  coefLider (consPol n b p) == b\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el resto de (consPol n b p) es p.\nprop_restoPol :: Int -> Int -> Polinomio Int -> Property\nprop_restoPol n b p =\n  n > grado p && b \/= 0 ==>\n  restoPol (consPol n b p) == p\n\n-- Verificaci\u00f3n\n-- ============\n\nreturn []\n\nverificaPol :: IO Bool\nverificaPol = $quickCheckAll\n\n-- La verificaci\u00f3n es\n--    \u03bb> verificaPol\n--    === prop_polCero_es_cero from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDensa.hs:157 ===\n--    +++ OK, passed 1 test.\n--\n--    === prop_consPol_no_cero from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDensa.hs:163 ===\n--    +++ OK, passed 100 tests; 274 discarded.\n--\n--    === prop_consPol from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDensa.hs:169 ===\n--    +++ OK, passed 100 tests.\n--\n--    === prop_grado from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDensa.hs:175 ===\n--    +++ OK, passed 100 tests; 297 discarded.\n--\n--    === prop_coefLider from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDensa.hs:182 ===\n--    +++ OK, passed 100 tests; 248 discarded.\n--\n--    === prop_restoPol from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDensa.hs:189 ===\n--    +++ OK, passed 100 tests; 322 discarded.\n--\n--    True\n<\/pre>\n<h4>2.4. Implementaci\u00f3n de polinomios mediante listas dispersas<\/h4>\n<p>Representaremos un polinomio mediante una lista de pares (grado,coef),<br \/>\nordenados en orden decreciente seg\u00fan el grado. Por ejemplo, el polinomio<\/p>\n<pre lang=\"text\">\n   6x^4 -5x^2 + 4x -7\n<\/pre>\n<p>se representa por<\/p>\n<pre lang=\"text\">\n   [(4,6),(2,-5),(1,4),(0,-7)]\n<\/pre>\n<p>En la representaci\u00f3n se supone que los primeros elementos de los pares forman una sucesi\u00f3n estrictamente decreciente y que los segundos elementos son distintos de cero.<\/p>\n<p>La implementaci\u00f3n se encuentra en el m\u00f3dulo <a href=\"https:\/\/bit.ly\/3ZUcwTz\">PolRepDispersa.hs<\/a> cuyo contenido es el siguiente:<\/p>\n<pre lang=\"haskell\">\n{-# LANGUAGE TemplateHaskell #-}\n{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}\n\nmodule TAD.PolRepDispersa\n  ( Polinomio,\n    polCero,   -- Polinomio a\n    esPolCero, -- Num a =>  Polinomio a -> Bool\n    consPol,   -- Num a => Int -> a -> Polinomio a -> Polinomio a\n    grado,     -- Polinomio a -> Int\n    coefLider, -- Num a => Polinomio a -> a\n    restoPol   -- Polinomio a -> Polinomio a\n  ) where\n\nimport Test.QuickCheck\n\nnewtype Polinomio a = Pol [(Int,a)]\n  deriving Eq\n\n-- (escribePol p) es la cadena correspondiente al polinomio p. Por\n-- ejemplo,\n--    \u03bb> escribePol (consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero)))\n--    \"3*x^4 + -5*x^2 + 3\"\nescribePol :: (Num a, Show a, Eq a) => Polinomio a -> String\nescribePol pol\n  | esPolCero pol         = \"0\"\n  | n == 0 && esPolCero p = show a\n  | n == 0                = concat [show a, \" + \", escribePol p]\n  | n == 1 && esPolCero p = show a ++ \"*x\"\n  | n == 1                = concat [show a, \"*x + \", escribePol p]\n  | a == 1 && esPolCero p = \"x^\" ++ show n\n  | esPolCero p           = concat [show a, \"*x^\", show n]\n  | a == 1                = concat [\"x^\", show n, \" + \", escribePol p]\n  | otherwise             = concat [show a, \"*x^\", show n, \" + \", escribePol p]\n  where n = grado pol\n        a = coefLider pol\n        p = restoPol pol\n\n-- Procedimiento de escritura de polinomios.\ninstance (Num a, Show a, Eq a) => Show (Polinomio a) where\n  show = escribePol\n\n-- Ejemplos de polinomios con coeficientes enteros:\nejPol1, ejPol2, ejPol3 :: Polinomio Int\nejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\nejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\nejPol3 = consPol 4 6 (consPol 1 2 polCero)\n\n-- Comprobaci\u00f3n de escritura:\n--    > ejPol1\n--    3*x^4 + -5*x^2 + 3\n--    > ejPol2\n--    x^5 + 5*x^2 + 4*x\n--    > ejPol3\n--    6*x^4 + 2*x\n\n-- polCero es el polinomio cero. Por ejemplo,\n--    \u03bb> polCero\n--    0\npolCero :: Num a => Polinomio a\npolCero = Pol []\n\n-- (esPolCero p) se verifica si p es el polinomio cero. Por ejemplo,\n--    esPolCero polCero  ==  True\n--    esPolCero ejPol1   ==  False\nesPolCero :: Num a => Polinomio a -> Bool\nesPolCero (Pol []) = True\nesPolCero _        = False\n\n-- (consPol n b p) es el polinomio bx^n+p. Por ejemplo,\n--    ejPol2               ==  x^5 + 5*x^2 + 4*x\n--    consPol 3 0 ejPol2   ==  x^5 + 5*x^2 + 4*x\n--    consPol 3 2 polCero  ==  2*x^3\n--    consPol 6 7 ejPol2   ==  7*x^6 + x^5 + 5*x^2 + 4*x\n--    consPol 4 7 ejPol2   ==  x^5 + 7*x^4 + 5*x^2 + 4*x\n--    consPol 5 7 ejPol2   ==  8*x^5 + 5*x^2 + 4*x\nconsPol :: (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a\nconsPol _ 0 p = p\nconsPol n b p@(Pol xs)\n    | esPolCero p = Pol [(n,b)]\n    | n > m       = Pol ((n,b):xs)\n    | n < m       = consPol m c (consPol n b (Pol (tail xs)))\n    | b+c == 0    = Pol (tail xs)\n    | otherwise   = Pol ((n,b+c) : tail xs)\n    where\n      c = coefLider p\n      m = grado p\n\n-- (grado p) es el grado del polinomio p. Por ejemplo,\n--    ejPol3        ==  6*x^4 + 2*x\n--    grado ejPol3  ==  4\ngrado :: Polinomio a -> Int\ngrado (Pol [])        = 0\ngrado (Pol ((n,_):_)) = n\n\n-- (coefLider p) es el coeficiente l\u00edder del polinomio p. Por ejemplo,\n--    ejPol3            ==  6*x^4 + 2*x\n--    coefLider ejPol3  ==  6\ncoefLider :: Num t => Polinomio t -> t\ncoefLider (Pol [])        = 0\ncoefLider (Pol ((_,b):_)) = b\n\n-- (restoPol p) es el resto del polinomio p. Por ejemplo,\n--    ejPol3           ==  6*x^4 + 2*x\n--    restoPol ejPol3  ==  2*x\n--    ejPol2           ==  x^5 + 5*x^2 + 4*x\n--    restoPol ejPol2  ==  5*x^2 + 4*x\nrestoPol :: Num t => Polinomio t -> Polinomio t\nrestoPol (Pol [])     = polCero\nrestoPol (Pol [_])    = polCero\nrestoPol (Pol (_:xs)) = Pol xs\n\n-- Generador de polinomios                                          --\n-- =======================\n\n-- genPolinomio es un generador de polinomios. Por ejemplo,\n--    \u03bb> sample (genPol 1)\n--    7*x^9 + 9*x^8 + 10*x^7 + -14*x^5 + -15*x^2 + -10\n--    -4*x^8 + 2*x\n--    -8*x^9 + 4*x^8 + 2*x^6 + 4*x^5 + -6*x^4 + 5*x^2 + -8*x\n--    -9*x^9 + x^5 + -7\n--    8*x^10 + -9*x^7 + 7*x^6 + 9*x^5 + 10*x^3 + -1*x^2\n--    7*x^10 + 5*x^9 + -5\n--    -8*x^10 + -7\n--    -5*x\n--    5*x^10 + 4*x^4 + -3\n--    3*x^3 + -4\n--    10*x\ngenPol :: (Num a, Arbitrary a, Eq a) => Int -> Gen (Polinomio a)\ngenPol 0 = return polCero\ngenPol _ = do\n  n <- choose (0,10)\n  b <- arbitrary\n  p <- genPol (div n 2)\n  return (consPol n b p)\n\ninstance (Num a, Arbitrary a, Eq a) => Arbitrary (Polinomio a) where\n  arbitrary = sized genPol\n\n-- Propiedades de los polinomios\n-- =============================\n\n-- polCero es el polinomio cero.\nprop_polCero_es_cero :: Bool\nprop_polCero_es_cero =\n  esPolCero polCero\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- (consPol n b p) es un polinomio distinto del cero.\nprop_consPol_no_cero :: Int -> Int -> Polinomio Int -> Property\nprop_consPol_no_cero n b p =\n  n > grado p && b \/= 0  ==>\n  not (esPolCero (consPol n b p))\n\n-- (consPol (grado p) (coefLider p) (restoPol p)) es igual a p.\nprop_consPol :: Polinomio Int -> Bool\nprop_consPol p =\n  consPol (grado p) (coefLider p) (restoPol p) == p\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el grado de (consPol n b p) es n.\nprop_grado :: Int -> Int -> Polinomio Int -> Property\nprop_grado n b p =\n  n > grado p && b \/= 0 ==>\n  grado (consPol n b p) == n\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el coeficiente l\u00edder de (consPol n b p) es b.\nprop_coefLider :: Int -> Int -> Polinomio Int -> Property\nprop_coefLider n b p =\n  n > grado p && b \/= 0 ==>\n  coefLider (consPol n b p) == b\n\n-- Si n es mayor que el grado de p y b no es cero, entonces\n-- el resto de (consPol n b p) es p.\nprop_restoPol :: Int -> Int -> Polinomio Int -> Property\nprop_restoPol n b p =\n  n > grado p && b \/= 0 ==>\n  restoPol (consPol n b p) == p\n\n-- Verificaci\u00f3n\n-- ============\n\nreturn []\n\nverificaPol :: IO Bool\nverificaPol = $quickCheckAll\n\n-- La verificaci\u00f3n es\n--    \u03bb> verificaPol\n--    === prop_polCero_es_cero from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDispersa.hs:156 ===\n--    +++ OK, passed 1 test.\n--\n--    === prop_consPol_no_cero from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDispersa.hs:162 ===\n--    +++ OK, passed 100 tests; 264 discarded.\n--\n--    === prop_consPol from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDispersa.hs:168 ===\n--    +++ OK, passed 100 tests.\n--\n--    === prop_grado from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDispersa.hs:174 ===\n--    +++ OK, passed 100 tests; 266 discarded.\n--\n--    === prop_coefLider from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDispersa.hs:181 ===\n--    +++ OK, passed 100 tests; 251 discarded.\n--\n--    === prop_restoPol from \/home\/jalonso\/alonso\/estudio\/Exercitium\/Exercitium\/src\/TAD\/PolRepDispersa.hs:188 ===\n--    +++ OK, passed 100 tests; 254 discarded.\n--\n--    True\n<\/pre>\n<h3>3. Los polinomios en Python<\/h3>\n<h4>3.1. El tipo abstracto de los polinomios en Python<\/h4>\n<p>La implementaci\u00f3n se encuentra en el m\u00f3dulo <a href=\"https:\/\/bit.ly\/3mmFu0R\">Polinomio.py<\/a> cuyo contenido es el siguiente:<\/p>\n<pre lang=\"python\">\n__all__ = [\n    'Polinomio',\n    'polCero',\n    'esPolCero',\n    'consPol',\n    'grado',\n    'coefLider',\n    'restoPol',\n    'polinomioAleatorio'\n]\n\nfrom src.TAD.PolRepDensa import (Polinomio, coefLider, consPol, esPolCero,\n                                 grado, polCero, polinomioAleatorio, restoPol)\n\n# from src.TAD.PolRepDispersa import (Polinomio, polCero, esPolCero,\n#                                     consPol, grado, coefLider,\n#                                     restoPol, polinomioAleatorio)\n<\/pre>\n<p>Para usar el TAD hay que usar una implementaci\u00f3n concreta. En principio, consideraremos las siguientes:<\/p>\n<ul>\n<li>mediante listas densas y<\/li>\n<li>mediante listas dispersas.<\/li>\n<\/ul>\n<h4>3.2. Implementaci\u00f3n de los polinomios mediante listas densas<\/h4>\n<p>Representaremos un polinomio por la lista de sus coeficientes ordenados en orden decreciente seg\u00fan el grado. Por ejemplo, el polinomio<\/p>\n<pre lang=\"text\">\n   6x^4 -5x^2 + 4x -7\n<\/pre>\n<p>se representa por<\/p>\n<pre lang=\"text\">\n   [6,0,-2,4,-7]\n<\/pre>\n<p>En la representaci\u00f3n se supone que, si la lista no es vac\u00eda, su primer elemento es distinto de cero.<\/p>\n<p>Se define la clase Polinomio con los siguientes m\u00e9todos:<\/p>\n<ul>\n<li>esPolCero() se verifica si es el polinomio cero.<\/li>\n<li>consPol(n, b) es el polinomio obtenido a\u00f1adiendo el t\u00e9rmiono bx^n<\/li>\n<li>grado() es el grado del polinomio.<\/li>\n<li>coefLider() es el coeficiente l\u00edder del polinomio.<\/li>\n<li>restoPol() es el resto del polinomio.<\/li>\n<\/ul>\n<p>Por ejemplo,<\/p>\n<pre lang=\"text\">\n   >>> Polinomio()\n   0\n   >>> ejPol1 = Polinomio().consPol(0,3).consPol(2,-5).consPol(4,3)\n   >>> ejPol1\n   3*x^4 + -5*x^2 + 3\n   >>> ejPol2 = Polinomio().consPol(1,4).consPol(2,5).consPol(5,1)\n   >>> ejPol2\n   x^5 + 5*x^2 + 4*x\n   >>> ejPol3 = Polinomio().consPol(1,2).consPol(4,6)\n   >>> ejPol3\n   6*x^4 + 2*x\n   >>> Polinomio().esPolCero()\n   True\n   >>> ejPol1.esPolCero()\n   False\n   >>> ejPol2\n   x^5 + 5*x^2 + 4*x\n   >>> ejPol2.consPol(3,0)\n   x^5 + 5*x^2 + 4*x\n   >>> Polinomio().consPol(3,2)\n   2*x^3\n   >>> ejPol2.consPol(6,7)\n   7*x^6 + x^5 + 5*x^2 + 4*x\n   >>> ejPol2.consPol(4,7)\n   x^5 + 7*x^4 + 5*x^2 + 4*x\n   >>> ejPol2.consPol(5,7)\n   8*x^5 + 5*x^2 + 4*x\n   >>> ejPol3\n   6*x^4 + 2*x\n   >>> ejPol3.grado()\n   4\n   >>> ejPol3.restoPol()\n   2*x\n   >>> ejPol2\n   x^5 + 5*x^2 + 4*x\n   >>> ejPol2.restoPol()\n   5*x^2 + 4*x\n<\/pre>\n<p>Adem\u00e1s se definen las correspondientes funciones. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   >>> polCero()\n   0\n   >>> ejPol1a = consPol(4,3,consPol(2,-5,consPol(0,3,polCero())))\n   >>> ejPol1a\n   3*x^4 + -5*x^2 + 3\n   >>> ejPol2a = consPol(5,1,consPol(2,5,consPol(1,4,polCero())))\n   >>> ejPol2a\n   x^5 + 5*x^2 + 4*x\n   >>> ejPol3a = consPol(4,6,consPol(1,2,polCero()))\n   >>> ejPol3a\n   6*x^4 + 2*x\n   >>> esPolCero(polCero())\n   True\n   >>> esPolCero(ejPol1a)\n   False\n   >>> ejPol2a\n   x^5 + 5*x^2 + 4*x\n   >>> consPol(3,9,ejPol2a)\n   x^5 + 9*x^3 + 5*x^2 + 4*x\n   >>> consPol(3,2,polCero())\n   2*x^3\n   >>> consPol(6,7,ejPol2a)\n   7*x^6 + x^5 + 5*x^2 + 4*x\n   >>> consPol(4,7,ejPol2a)\n   x^5 + 7*x^4 + 5*x^2 + 4*x\n   >>> consPol(5,7,ejPol2a)\n   8*x^5 + 5*x^2 + 4*x\n   >>> ejPol3a\n   6*x^4 + 2*x\n   >>> grado(ejPol3a)\n   4\n   >>> restoPol(ejPol3a)\n   2*x\n   >>> ejPol2a\n   x^5 + 5*x^2 + 4*x\n   >>> restoPol(ejPol2a)\n   5*x^2 + 4*x\n<\/pre>\n<p>Finalmente, se define un generador aleatorio de polinomios y se comprueba que los polinomios cumplen las propiedades de su especificaci\u00f3n.<\/p>\n<p>La implementaci\u00f3n se encuentra en el m\u00f3dulo <a href=\"http:\/\/bit.ly\/3Kvz8Es\">PolRepDensa.py<\/a> en el que se define la clase Conj con los siguientes m\u00e9todos:<\/p>\n<pre lang=\"python\">\nfrom __future__ import annotations\n\n__all__ = [\n    'Polinomio',\n    'polCero',\n    'esPolCero',\n    'consPol',\n    'grado',\n    'coefLider',\n    'restoPol',\n    'polinomioAleatorio'\n]\n\nfrom dataclasses import dataclass, field\nfrom itertools import dropwhile\nfrom typing import Generic, TypeVar\n\nfrom hypothesis import assume, given\nfrom hypothesis import strategies as st\n\nA = TypeVar('A', int, float, complex)\n\n# Clase de los polinomios mediante listas densas\n# ==============================================\n\n@dataclass\nclass Polinomio(Generic[A]):\n    _coeficientes: list[A] = field(default_factory=list)\n\n    def esPolCero(self) -> bool:\n        return not self._coeficientes\n\n    def grado(self) -> int:\n        if self.esPolCero():\n            return 0\n        return len(self._coeficientes) - 1\n\n    def coefLider(self) -> A:\n        if self.esPolCero():\n            return 0\n        return self._coeficientes[0]\n\n    def restoPol(self) -> Polinomio[A]:\n        xs = self._coeficientes\n        if len(xs) <= 1:\n            return Polinomio([])\n        if xs[1] == 0:\n            return Polinomio(list(dropwhile(lambda x: x == 0, xs[2:])))\n        return Polinomio(xs[1:])\n\n    def consPol(self, n: int, b: A) -> Polinomio[A]:\n        m = self.grado()\n        c = self.coefLider()\n        xs = self._coeficientes\n        if self.esPolCero():\n            return Polinomio([b] + ([0] * n))\n        if n > m:\n            return Polinomio([b] + ([0] * (n-m-1)) + xs)\n        if n < m:\n            return self.restoPol().consPol(n, b).consPol(m, c)\n        if b + c == 0:\n            return Polinomio(list(dropwhile(lambda x: x == 0, xs[1:])))\n        return Polinomio([b + c] + xs[1:])\n\n    def __repr__(self) -> str:\n        n = self.grado()\n        a = self.coefLider()\n        p = self.restoPol()\n        if self.esPolCero():\n            return \"0\"\n        if n == 0 and p.esPolCero():\n            return str(a)\n        if n == 0:\n            return str(a) + \" + \" + str(p)\n        if n == 1 and p.esPolCero():\n            return str(a) + \"*x\"\n        if n == 1:\n            return str(a) + \"*x + \" + str(p)\n        if a == 1 and p.esPolCero():\n            return \"x^\" + str(n)\n        if p.esPolCero():\n            return str(a) + \"*x^\" + str(n)\n        if a == 1:\n            return \"x^\" + str(n) + \" + \" + str(p)\n        return str(a) + \"*x^\" + str(n) + \" + \" + str(p)\n\n# Funciones del tipo polinomio\n# ============================\n\ndef polCero() -> Polinomio[A]:\n    return Polinomio([])\n\ndef esPolCero(p: Polinomio[A]) -> bool:\n    return p.esPolCero()\n\ndef grado(p: Polinomio[A]) -> int:\n    return p.grado()\n\ndef coefLider(p: Polinomio[A]) -> A:\n    return p.coefLider()\n\ndef restoPol(p: Polinomio[A]) -> Polinomio[A]:\n    return p.restoPol()\n\ndef consPol(n: int, b: A, p: Polinomio[A]) -> Polinomio[A]:\n    return p.consPol(n, b)\n\n# Generador de polinomios\n# =======================\n\n# normal(xs) es la lista obtenida eliminando los ceros iniciales de\n# xs. Por ejmplo,\n#    >>> normal([0,0,5,0])\n#    [5, 0]\n#    >>> normal([0,0,0,0])\n#    []\ndef normal(xs: list[A]) -> list[A]:\n    return list(dropwhile(lambda x: x == 0, xs))\n\n# polinomioAleatorio() genera polinomios aleatorios. Por ejemplo,\n#    >>> polinomioAleatorio().example()\n#    9*x^6 + -7*x^5 + 7*x^3 + x^2 + 7\n#    >>> polinomioAleatorio().example()\n#    -3*x^7 + 8*x^6 + 2*x^5 + x^4 + -1*x^3 + -6*x^2 + 8*x + -6\n#    >>> polinomioAleatorio().example()\n#    x^2 + 7*x + -1\ndef polinomioAleatorio() -> st.SearchStrategy[Polinomio[int]]:\n    return st.lists(st.integers(min_value=-9, max_value=9), max_size=10)\\\n             .map(lambda xs: normal(xs))\\\n             .map(Polinomio)\n\n# Comprobaci\u00f3n de las propiedades de los polinomios\n# =================================================\n\n# Las propiedades son\ndef test_esPolCero1() -> None:\n    assert esPolCero(polCero())\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_esPolCero2(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert not esPolCero(consPol(n, b, p))\n\n@given(p=polinomioAleatorio())\ndef test_consPol(p: Polinomio[int]) -> None:\n    assume(not esPolCero(p))\n    assert consPol(grado(p), coefLider(p), restoPol(p)) == p\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_grado(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert grado(consPol(n, b, p)) == n\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_coefLider(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert coefLider(consPol(n, b, p)) == b\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_restoPol(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert restoPol(consPol(n, b, p)) == p\n\n# La comprobaci\u00f3n es\n#    > poetry run pytest -v PolRepDensa.py\n#\n#    PolRepDensa.py::test_esPolCero1 PASSED\n#    PolRepDensa.py::test_esPolCero2 PASSED\n#    PolRepDensa.py::test_consPol PASSED\n#    PolRepDensa.py::test_grado PASSED\n#    PolRepDensa.py::test_coefLider PASSED\n#    PolRepDensa.py::test_restoPol PASSED\n#\n#    === 6 passed in 1.64s ===\n<\/pre>\n<h4>3.3. Implementaci\u00f3n de los polinomios mediante listas dispersas<\/h4>\n<p>Representaremos un polinomio mediante una lista de pares (grado,coef), ordenados en orden decreciente seg\u00fan el grado. Por ejemplo, el polinomio<\/p>\n<pre lang=\"text\">\n   6x^4 -5x^2 + 4x -7\n<\/pre>\n<p>se representa por<\/p>\n<pre lang=\"text\">\n   [(4,6),(2,-5),(1,4),(0,-7)]\n<\/pre>\n<p>En la representaci\u00f3n se supone que los primeros elementos de los pares forman una sucesi\u00f3n estrictamente decreciente y que los segundos elementos son distintos de cero.<\/p>\n<p>La implementaci\u00f3n se encuentra en el m\u00f3dulo <a href=\"https:\/\/bit.ly\/3UrnU8l\">PolRepDispersa.py<\/a> cuyo contenido es<\/p>\n<pre lang=\"python\">\nfrom __future__ import annotations\n\n__all__ = [\n    'Polinomio',\n    'polCero',\n    'esPolCero',\n    'consPol',\n    'grado',\n    'coefLider',\n    'restoPol',\n    'polinomioAleatorio'\n]\n\nfrom dataclasses import dataclass, field\nfrom typing import Generic, TypeVar\n\nfrom hypothesis import assume, given\nfrom hypothesis import strategies as st\n\nA = TypeVar('A', int, float, complex)\n\n# Clase de los polinomios mediante listas densas\n# ==============================================\n\n@dataclass\nclass Polinomio(Generic[A]):\n    _terminos: list[tuple[int, A]] = field(default_factory=list)\n\n    def esPolCero(self) -> bool:\n        return not self._terminos\n\n    def grado(self) -> int:\n        if self.esPolCero():\n            return 0\n        return self._terminos[0][0]\n\n    def coefLider(self) -> A:\n        if self.esPolCero():\n            return 0\n        return self._terminos[0][1]\n\n    def restoPol(self) -> Polinomio[A]:\n        xs = self._terminos\n        if len(xs) <= 1:\n            return Polinomio([])\n        return Polinomio(xs[1:])\n\n    def consPol(self, n: int, b: A) -> Polinomio[A]:\n        m = self.grado()\n        c = self.coefLider()\n        xs = self._terminos\n        if b == 0:\n            return self\n        if self.esPolCero():\n            return Polinomio([(n, b)])\n        if n > m:\n            return Polinomio([(n, b)] + xs)\n        if n < m:\n            return Polinomio(xs[1:]).consPol(n, b).consPol(m, c)\n        if b + c == 0:\n            return Polinomio(xs[1:])\n        return Polinomio([(n, b + c)] + xs[1:])\n\n    def __repr__(self) -> str:\n        n = self.grado()\n        a = self.coefLider()\n        p = self.restoPol()\n        if self.esPolCero():\n            return \"0\"\n        if n == 0 and p.esPolCero():\n            return str(a)\n        if n == 0:\n            return str(a) + \" + \" + str(p)\n        if n == 1 and p.esPolCero():\n            return str(a) + \"*x\"\n        if n == 1:\n            return str(a) + \"*x + \" + str(p)\n        if a == 1 and p.esPolCero():\n            return \"x^\" + str(n)\n        if p.esPolCero():\n            return str(a) + \"*x^\" + str(n)\n        if a == 1:\n            return \"x^\" + str(n) + \" + \" + str(p)\n        return str(a) + \"*x^\" + str(n) + \" + \" + str(p)\n\n# Funciones del tipo polinomio\n# ============================\n\ndef polCero() -> Polinomio[A]:\n    return Polinomio([])\n\ndef esPolCero(p: Polinomio[A]) -> bool:\n    return p.esPolCero()\n\ndef grado(p: Polinomio[A]) -> int:\n    return p.grado()\n\ndef coefLider(p: Polinomio[A]) -> A:\n    return p.coefLider()\n\ndef restoPol(p: Polinomio[A]) -> Polinomio[A]:\n    return p.restoPol()\n\ndef consPol(n: int, b: A, p: Polinomio[A]) -> Polinomio[A]:\n    return p.consPol(n, b)\n\n# Generador de polinomios\n# =======================\n\n# normal(ps) es la representaci\u00f3n dispersa de un polinomio.\ndef normal(ps: list[tuple[int, A]]) -> list[tuple[int, A]]:\n    xs = sorted(list({p[0] for p in ps}), reverse=True)\n    ys = [p[1] for p in ps]\n    return [(x, y) for (x, y) in zip(xs, ys) if y != 0]\n\n# polinomioAleatorio() genera polinomios aleatorios. Por ejemplo,\n#    >>> polinomioAleatorio().example()\n#    -4*x^8 + -5*x^7 + -4*x^6 + -4*x^5 + -8*x^3\n#    >>> polinomioAleatorio().example()\n#    -7*x^9 + -8*x^6 + -8*x^3 + 2*x^2 + -1*x + 4\ndef polinomioAleatorio() -> st.SearchStrategy[Polinomio[int]]:\n    return st.lists(st.tuples(st.integers(min_value=0, max_value=9),\n                              st.integers(min_value=-9, max_value=9)))\\\n             .map(lambda ps: normal(ps))\\\n             .map(Polinomio)\n\n# Comprobaci\u00f3n de las propiedades de los polinomios\n# =================================================\n\n# Las propiedades son\ndef test_esPolCero1() -> None:\n    assert esPolCero(polCero())\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_esPolCero2(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert not esPolCero(consPol(n, b, p))\n\n@given(p=polinomioAleatorio())\ndef test_consPol(p: Polinomio[int]) -> None:\n    assume(not esPolCero(p))\n    assert consPol(grado(p), coefLider(p), restoPol(p)) == p\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_grado(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert grado(consPol(n, b, p)) == n\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_coefLider(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert coefLider(consPol(n, b, p)) == b\n\n@given(p=polinomioAleatorio(),\n       n=st.integers(min_value=0, max_value=10),\n       b=st.integers())\ndef test_restoPol(p: Polinomio[int], n: int, b: int) -> None:\n    assume(n > grado(p) and b != 0)\n    assert restoPol(consPol(n, b, p)) == p\n\n# La comprobaci\u00f3n es\n#    > poetry run pytest -v PolRepDispersa.py\n#\n#    PolRepDispersa.py::test_esPolCero1 PASSED\n#    PolRepDispersa.py::test_esPolCero2 PASSED\n#    PolRepDispersa.py::test_consPol PASSED\n#    PolRepDispersa.py::test_grado PASSED\n#    PolRepDispersa.py::test_coefLider PASSED\n#    PolRepDispersa.py::test_restoPol PASSED\n#\n#    === 6 passed in 1.74s ===\n<\/pre>\n<p><a name=\"ej2\"><\/a><\/p>\n<h3>2. Transformaciones entre las representaciones dispersa y densa de polinomios<\/h3>\n<p>Definir las funciones<\/p>\n<pre lang=\"text\">\n   densaAdispersa :: (Num a, Eq a) => [a] -> [(Int,a)]\n   dispersaAdensa :: (Num a, Eq a) => [(Int,a)] -> [a]\n<\/pre>\n<p>tales que<\/p>\n<ul>\n<li><code>densaAdispersa xs<\/code> es la representaci\u00f3n dispersa del polinomio cuya representaci\u00f3n densa es <code>xs<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     \u03bb> densaAdispersa [9,0,0,5,0,4,7]\n     [(6,9),(3,5),(1,4),(0,7)]\n<\/pre>\n<ul>\n<li><code>dispersaAdensa ps<\/code> es la representaci\u00f3n densa del polinomio cuya representaci\u00f3n dispersa es <code>ps<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     \u03bb> dispersaAdensa [(6,9),(3,5),(1,4),(0,7)]\n     [9,0,0,5,0,4,7]\n<\/pre>\n<p>Comprobar con QuickCheck que las funciones densaAdispersa y dispersaAdensa son inversas.<\/p>\n<p><b>Soluciones<\/b><\/p>\n<p>A continuaci\u00f3n se muestran las <a href=\"#haskell\">soluciones en Haskell<\/a> y las <a href=\"#python\">soluciones en Python<\/a>.<\/p>\n<p><a name=\"haskell\"><\/a><br \/>\n<b>Soluciones en Haskell<\/b><\/p>\n<pre lang=\"haskell\">\nimport Data.List (nub, sort)\nimport Test.QuickCheck\n\n-- 1\u00aa definici\u00f3n de densaAdispersa\n-- ===============================\n\ndensaAdispersa :: (Num a, Eq a) => [a] -> [(Int,a)]\ndensaAdispersa xs = [(m,a) | (m,a) <- zip [n-1,n-2..] xs, a \/= 0]\n  where n  = length xs\n\n-- 2\u00aa definici\u00f3n de densaAdispersa\n-- ===============================\n\ndensaAdispersa2 :: (Num a, Eq a) => [a] -> [(Int,a)]\ndensaAdispersa2 xs = reverse (aux (reverse xs) 0)\n  where aux [] _ = []\n        aux (0:ys) n = aux ys (n+1)\n        aux (y:ys) n = (n,y) : aux ys (n+1)\n\n-- Comprobaci\u00f3n de equivalencia de densaAdispersa\n-- ==============================================\n\n-- La propiedad es\nprop_densaAdispersa :: [Int] -> Bool\nprop_densaAdispersa xs =\n  densaAdispersa xs == densaAdispersa2 xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_densaAdispersa\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> densaAdispersa (5 : replicate (10^7) 0)\n--    [(10000000,5)]\n--    (4.54 secs, 3,280,572,504 bytes)\n--    \u03bb> densaAdispersa2 (5 : replicate (10^7) 0)\n--    [(10000000,5)]\n--    (7.35 secs, 3,696,968,576 bytes)\n\n-- 1\u00aa definici\u00f3n de dispersaAdensa\n-- ===============================\n\ndispersaAdensa :: (Num a, Eq a) => [(Int,a)] -> [a]\ndispersaAdensa []      = []\ndispersaAdensa [(n,a)] = a : replicate n 0\ndispersaAdensa ((n,a):(m,b):ps) =\n  a : replicate (n-m-1) 0 ++ dispersaAdensa ((m,b):ps)\n\n-- 2\u00aa definici\u00f3n de dispersaAdensa\n-- ===============================\n\ndispersaAdensa2 :: (Num a, Eq a) => [(Int,a)] -> [a]\ndispersaAdensa2 []           = []\ndispersaAdensa2 ps@((n,_):_) =\n  [coeficiente ps m | m <- [n,n-1..0]]\n\n-- (coeficiente ps n) es el coeficiente del t\u00e9rmino de grado n en el\n-- polinomio cuya representaci\u00f3n densa es ps. Por ejemplo,\n--    coeficiente [(6,9),(3,5),(1,4),(0,7)] 3  ==  5\n--    coeficiente [(6,9),(3,5),(1,4),(0,7)] 4  ==  0\ncoeficiente :: (Num a, Eq a) => [(Int,a)] -> Int -> a\ncoeficiente [] _                     = 0\ncoeficiente ((m,a):ps) n | n > m     = 0\n                         | n == m    = a\n                         | otherwise = coeficiente ps n\n\n-- Comprobaci\u00f3n de equivalencia de dispersaAdensa\n-- ==============================================\n\n-- Tipo de las representaciones dispersas de polinomios.\nnewtype Dispersa = Dis [(Int,Int)]\n  deriving Show\n\n-- dispersaArbitraria es un generador de representaciones dispersas de\n-- polinomios. Por ejemplo,\n--    \u03bb> sample dispersaArbitraria\n--    Dis []\n--    Dis []\n--    Dis [(3,-2),(2,0),(0,3)]\n--    Dis [(6,1),(4,-2),(3,4),(2,-4)]\n--    Dis []\n--    Dis [(5,-7)]\n--    Dis [(12,5),(11,-8),(10,3),(8,-10),(7,-5),(4,12),(3,6),(2,-8),(1,11)]\n--    Dis [(7,-2),(2,-8)]\n--    Dis [(14,-15)]\n--    Dis [(17,5),(16,1),(15,-1),(14,10),(13,5),(12,-15),(9,12),(6,14)]\n--    Dis [(19,17),(12,7),(8,-3),(7,13),(5,-2),(4,7)]\ndispersaArbitraria :: Gen Dispersa\ndispersaArbitraria = do\n  (xs, ys) <- arbitrary\n  let xs' = nub (reverse (sort (map abs xs)))\n      ys' = filter (\/= 0) ys\n  return (Dis (zip xs' ys'))\n\n-- Dispersa est\u00e1 contenida en Arbitrary\ninstance Arbitrary Dispersa where\n  arbitrary = dispersaArbitraria\n\n-- La propiedad es\nprop_dispersaAdensa :: Dispersa -> Bool\nprop_dispersaAdensa (Dis xs) =\n  dispersaAdensa xs == dispersaAdensa2 xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_dispersaAdensa\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia de dispersaAdensa\n-- ===========================================\n\n-- La comparaci\u00f3n es\n--    \u03bb> length (dispersaAdensa [(10^7,5)])\n--    10000001\n--    (0.11 secs, 560,566,848 bytes)\n--    \u03bb> length (dispersaAdensa2 [(10^7,5)])\n--    10000001\n--    (2.51 secs, 2,160,567,112 bytes)\n\n-- Propiedad\n-- =========\n\n-- Tipo de las representaciones densas de polinomios.\nnewtype Densa = Den [Int]\n  deriving Show\n\n-- densaArbitraria es un generador de representaciones dispersas de\n-- polinomios. Por ejemplo,\n--    \u03bb> sample densaArbitraria\n--    Den []\n--    Den []\n--    Den []\n--    Den [-6,6,5,-3]\n--    Den []\n--    Den [8,-7,-10,8,-10,-4,10,6,10]\n--    Den [-6,2,11,-4,-9,-5,9,2,2,9]\n--    Den [-6,9,-2]\n--    Den [-1,-7,15,1,5,-2,13,16,8,7,2,16,-2,16,-7,4]\n--    Den [8,13,-4,-2,-10,3,5,-4,-6,13,-9,-12,8,11,9,-18,12,10]\n--    Den [-1,-2,11,17,-7,13,-12,-19,16,-10,-18,-19,1,-4,-17,10,1,10]\ndensaArbitraria :: Gen Densa\ndensaArbitraria = do\n  ys <- arbitrary\n  let ys' = dropWhile (== 0) ys\n  return (Den ys')\n\n-- Dispersa est\u00e1 contenida en Arbitrary\ninstance Arbitrary Densa where\n  arbitrary = densaArbitraria\n\n-- La primera propiedad es\nprop_dispersaAdensa_densaAdispersa :: Densa -> Bool\nprop_dispersaAdensa_densaAdispersa (Den xs) =\n  dispersaAdensa (densaAdispersa xs) == xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_dispersaAdensa_densaAdispersa\n--    +++ OK, passed 100 tests.\n\n-- La segunda propiedad es\nprop_densaAdispersa_dispersaAdensa :: Dispersa -> Bool\nprop_densaAdispersa_dispersaAdensa (Dis ps) =\n  densaAdispersa (dispersaAdensa ps) == ps\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_densaAdispersa_dispersaAdensa\n--    +++ OK, passed 100 tests.\n<\/pre>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom itertools import dropwhile\nfrom typing import TypeVar\n\nfrom hypothesis import given\nfrom hypothesis import strategies as st\n\nA = TypeVar('A', int, float, complex)\n\n# 1\u00aa definici\u00f3n de densaAdispersa\n# ===============================\n\ndef densaAdispersa(xs: list[A]) -> list[tuple[int, A]]:\n    n = len(xs)\n    return [(m, a) for (m, a) in zip(range(n-1, -1, -1),  xs) if a != 0]\n\n# 2\u00aa definici\u00f3n de densaAdispersa\n# ===============================\n\ndef densaAdispersa2(xs: list[A]) -> list[tuple[int, A]]:\n    def aux(xs: list[A], n: int) -> list[tuple[int, A]]:\n        if not xs:\n            return []\n        if xs[0] == 0:\n            return aux(xs[1:], n + 1)\n        return [(n, xs[0])] + aux(xs[1:], n + 1)\n\n    return list(reversed(aux(list(reversed(xs)), 0)))\n\n# 3\u00aa definici\u00f3n de densaAdispersa\n# ===============================\n\ndef densaAdispersa3(xs: list[A]) -> list[tuple[int, A]]:\n    r = []\n    n = len(xs) - 1\n    for x in xs:\n        if x != 0:\n            r.append((n, x))\n        n -= 1\n    return r\n\n# Comprobaci\u00f3n de equivalencia de densaAdispersa\n# ==============================================\n\n# normalDensa(ps) es la representaci\u00f3n dispersa de un polinomio.\ndef normalDensa(xs: list[A]) -> list[A]:\n    return list(dropwhile(lambda x: x == 0, xs))\n\n# densaAleatoria() genera representaciones densas de polinomios\n# aleatorios. Por ejemplo,\n#    >>> densaAleatoria().example()\n#    [-5, 9, -6, -5, 7, -5, -1, 9]\n#    >>> densaAleatoria().example()\n#    [-4, 9, -3, -3, -5, 0, 6, -8, 8, 6, 0, -9]\n#    >>> densaAleatoria().example()\n#    [-3, -1, 2, 0, -9]\ndef densaAleatoria() -> st.SearchStrategy[list[int]]:\n    return st.lists(st.integers(min_value=-9, max_value=9))\\\n             .map(normalDensa)\n\n# La propiedad es\n@given(xs=densaAleatoria())\ndef test_densaADispersa(xs: list[int]) -> None:\n    r = densaAdispersa(xs)\n    assert densaAdispersa2(xs) == r\n    assert densaAdispersa3(xs) == r\n\n# 1\u00aa definici\u00f3n de dispersaAdensa\n# ===============================\n\ndef dispersaAdensa(ps: list[tuple[int, A]]) -> list[A]:\n    if not ps:\n        return []\n    if len(ps) == 1:\n        return [ps[0][1]] + [0] * ps[0][0]\n    (n, a) = ps[0]\n    (m, _) = ps[1]\n    return [a] + [0] * (n-m-1) + dispersaAdensa(ps[1:])\n\n# 2\u00aa definici\u00f3n de dispersaAdensa\n# ===============================\n\n# coeficiente(ps, n) es el coeficiente del t\u00e9rmino de grado n en el\n# polinomio cuya representaci\u00f3n densa es ps. Por ejemplo,\n#    coeficiente([(6, 9), (3, 5), (1, 4), (0, 7)], 3)  ==  5\n#    coeficiente([(6, 9), (3, 5), (1, 4), (0, 7)], 4)  ==  0\ndef coeficiente(ps: list[tuple[int, A]], n: int) -> A:\n    if not ps:\n        return 0\n    (m, a) = ps[0]\n    if n > m:\n        return 0\n    if n == m:\n        return a\n    return coeficiente(ps[1:], n)\n\ndef dispersaAdensa2(ps: list[tuple[int, A]]) -> list[A]:\n    if not ps:\n        return []\n    n = ps[0][0]\n    return [coeficiente(ps, m) for m in range(n, -1, -1)]\n\n# 3\u00aa definici\u00f3n de dispersaAdensa\n# ===============================\n\ndef dispersaAdensa3(ps: list[tuple[int, A]]) -> list[A]:\n    if not ps:\n        return []\n    n = ps[0][0]\n    r: list[A] = [0] * (n + 1)\n    for (m, a) in ps:\n        r[n-m] = a\n    return r\n\n# Comprobaci\u00f3n de equivalencia de dispersaAdensa\n# ==============================================\n\n# normalDispersa(ps) es la representaci\u00f3n dispersa de un polinomio.\ndef normalDispersa(ps: list[tuple[int, A]]) -> list[tuple[int, A]]:\n    xs = sorted(list({p[0] for p in ps}), reverse=True)\n    ys = [p[1] for p in ps]\n    return [(x, y) for (x, y) in zip(xs, ys) if y != 0]\n\n# dispersaAleatoria() genera representaciones densas de polinomios\n# aleatorios. Por ejemplo,\n#    >>> dispersaAleatoria().example()\n#    [(5, -6), (2, -1), (0, 2)]\n#    >>> dispersaAleatoria().example()\n#    [(6, -7)]\n#    >>> dispersaAleatoria().example()\n#    [(7, 2), (4, 9), (3, 3), (0, -2)]\ndef dispersaAleatoria() -> st.SearchStrategy[list[tuple[int, int]]]:\n    return st.lists(st.tuples(st.integers(min_value=0, max_value=9),\n                              st.integers(min_value=-9, max_value=9)))\\\n             .map(normalDispersa)\n\n# La propiedad es\n@given(ps=dispersaAleatoria())\ndef test_dispersaAdensa(ps: list[tuple[int, int]]) -> None:\n    r = dispersaAdensa(ps)\n    assert dispersaAdensa2(ps) == r\n    assert dispersaAdensa3(ps) == r\n\n# Propiedad\n# =========\n\n# La primera propiedad es\n@given(xs=densaAleatoria())\ndef test_dispersaAdensa_densaAdispersa(xs: list[int]) -> None:\n    assert dispersaAdensa(densaAdispersa(xs)) == xs\n\n# La segunda propiedad es\n@given(ps=dispersaAleatoria())\ndef test_densaAdispersa_dispersaAdensa(ps: list[tuple[int, int]]) -> None:\n    assert densaAdispersa(dispersaAdensa(ps)) == ps\n\n# La comprobaci\u00f3n es\n#    > poetry run pytest -v Polinomios_Transformaciones_dispersa_y_densa.py\n#    test_densaADispersa PASSED\n#    test_dispersaAdensa PASSED\n#    test_dispersaAdensa_densaAdispersa PASSED\n#    test_densaAdispersa_dispersaAdensa PASSED\n<\/pre>\n<p><a name=\"ej3\"><\/a><\/p>\n<h3>3. Transformaciones entre polinomios y listas dispersas<\/h3>\n<p>Utilizando el <a href=\"https:\/\/bit.ly\/3KwqXYu\">tipo abstracto de datos de los polinomios<\/a> definir las funciones<\/p>\n<pre lang=\"text\">\n   dispersaApolinomio :: (Num a, Eq a) => [(Int,a)] -> Polinomio a\n   polinomioAdispersa :: (Num a, Eq a) => Polinomio a -> [(Int,a)]\n<\/pre>\n<p>tales que<\/p>\n<ul>\n<li><code>dispersaApolinomio ps<\/code> es el polinomiocuya representaci\u00f3n dispersa es <code>ps<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     \u03bb> dispersaApolinomio [(6,9),(3,5),(1,4),(0,7)]\n     9*x^6 + 5*x^3 + 4*x + 7\n<\/pre>\n<ul>\n<li><code>polinomioAdispersa p<\/code> es la representaci\u00f3n dispersa del polinomio <code>p<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     \u03bb> ejPol = consPol 6 9 (consPol 3 5 (consPol 1 4 (consPol 0 7 polCero)))\n     \u03bb> ejPol\n     9*x^6 + 5*x^3 + 4*x + 7\n     \u03bb> polinomioAdispersa ejPol\n     [(6,9),(3,5),(1,4),(0,7)]\n<\/pre>\n<p>Comprobar con QuickCheck que ambas funciones son inversas.<\/p>\n<p><b>Soluciones<\/b><\/p>\n<p>A continuaci\u00f3n se muestran las <a href=\"#haskell\">soluciones en Haskell<\/a> y las <a href=\"#python\">soluciones en Python<\/a>.<\/p>\n<p><a name=\"haskell\"><\/a><br \/>\n<b>Soluciones en Haskell<\/b><\/p>\n<pre lang=\"haskell\">\nimport TAD.Polinomio (Polinomio, polCero, esPolCero, consPol, grado,\n                      coefLider, restoPol)\nimport Data.List (sort, nub)\nimport Test.QuickCheck\n\n-- 1\u00aa definici\u00f3n de dispersaApolinomio\n-- ===================================\n\ndispersaApolinomio :: (Num a, Eq a) => [(Int,a)] -> Polinomio a\ndispersaApolinomio []         = polCero\ndispersaApolinomio ((n,a):ps) = consPol n a (dispersaApolinomio ps)\n\n-- 2\u00aa definici\u00f3n de dispersaApolinomio\n-- ===================================\n\ndispersaApolinomio2 :: (Num a, Eq a) => [(Int,a)] -> Polinomio a\ndispersaApolinomio2 = foldr (\\(x,y) -> consPol x y) polCero\n\n\n-- 3\u00aa definici\u00f3n de dispersaApolinomio\n-- ===================================\n\ndispersaApolinomio3 :: (Num a, Eq a) => [(Int,a)] -> Polinomio a\ndispersaApolinomio3 = foldr (uncurry consPol) polCero\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- Tipo de las representaciones dispersas de polinomios.\nnewtype Dispersa = Dis [(Int,Int)]\n  deriving Show\n\n-- dispersaArbitraria es un generador de representaciones dispersas de\n-- polinomios. Por ejemplo,\n--    \u03bb> sample dispersaArbitraria\n--    Dis []\n--    Dis []\n--    Dis [(3,-2),(2,0),(0,3)]\n--    Dis [(6,1),(4,-2),(3,4),(2,-4)]\n--    Dis []\n--    Dis [(5,-7)]\n--    Dis [(12,5),(11,-8),(10,3),(8,-10),(7,-5),(4,12),(3,6),(2,-8),(1,11)]\n--    Dis [(7,-2),(2,-8)]\n--    Dis [(14,-15)]\n--    Dis [(17,5),(16,1),(15,-1),(14,10),(13,5),(12,-15),(9,12),(6,14)]\n--    Dis [(19,17),(12,7),(8,-3),(7,13),(5,-2),(4,7)]\ndispersaArbitraria :: Gen Dispersa\ndispersaArbitraria = do\n  (xs, ys) <- arbitrary\n  let xs' = nub (reverse (sort (map abs xs)))\n      ys' = filter (\/= 0) ys\n  return (Dis (zip xs' ys'))\n\n-- Dispersa est\u00e1 contenida en Arbitrary\ninstance Arbitrary Dispersa where\n  arbitrary = dispersaArbitraria\n\n-- La propiedad es\nprop_dispersaApolinomio :: Dispersa -> Bool\nprop_dispersaApolinomio (Dis ps) =\n  all (== dispersaApolinomio ps)\n      [dispersaApolinomio2 ps,\n       dispersaApolinomio3 ps]\n\n-- Definici\u00f3n de polinomioAdispersa\n-- ================================\n\npolinomioAdispersa :: (Num a, Eq a) => Polinomio a -> [(Int,a)]\npolinomioAdispersa p\n  | esPolCero p = []\n  | otherwise   = (grado p, coefLider p) : polinomioAdispersa (restoPol p)\n\n-- Propiedad de ser inversas\n-- =========================\n\n-- La primera propiedad es\nprop_polinomioAdispersa_dispersaApolinomio :: Dispersa -> Bool\nprop_polinomioAdispersa_dispersaApolinomio (Dis ps) =\n  polinomioAdispersa (dispersaApolinomio ps) == ps\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_polinomioAdispersa_dispersaApolinomio\n--    +++ OK, passed 100 tests.\n\n-- La segunda propiedad es\nprop_dispersaApolinomio_polinomioAdispersa :: Polinomio Int -> Bool\nprop_dispersaApolinomio_polinomioAdispersa p =\n  dispersaApolinomio (polinomioAdispersa p) == p\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_dispersaApolinomio_polinomioAdispersa\n--    +++ OK, passed 100 tests.\n<\/pre>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom typing import TypeVar\n\nfrom hypothesis import given\n\nfrom src.Polinomios_Transformaciones_dispersa_y_densa import dispersaAleatoria\nfrom src.TAD.Polinomio import (Polinomio, coefLider, consPol, esPolCero, grado,\n                               polCero, polinomioAleatorio, restoPol)\n\nA = TypeVar('A', int, float, complex)\n\n\n# 1\u00aa definici\u00f3n de dispersaApolinomio\n# ===================================\n\ndef dispersaApolinomio(ps: list[tuple[int, A]]) -> Polinomio[A]:\n    if not ps:\n        return polCero()\n    (n, a) = ps[0]\n    return consPol(n, a, dispersaApolinomio(ps[1:]))\n\n# 2\u00aa definici\u00f3n de dispersaApolinomio\n# ===================================\n\ndef dispersaApolinomio2(ps: list[tuple[int, A]]) -> Polinomio[A]:\n    r: Polinomio[A] = polCero()\n    for (n, a) in reversed(ps):\n        r = consPol(n, a, r)\n    return r\n\n# Comprobaci\u00f3n de equivalencia\n# ============================\n\n# La propiedad es\n@given(ps=dispersaAleatoria())\ndef test_dispersaApolinomio(ps: list[tuple[int, int]]) -> None:\n    assert dispersaApolinomio(ps) == dispersaApolinomio2(ps)\n\n# El generador dispersaAleatoria est\u00e1 definido en el ejercicio\n# \"Transformaciones entre las representaciones dispersa y densa\" que se\n# encuentra en https:\/\/bit.ly\/402UpuT\n\n# Definici\u00f3n de polinomioAdispersa\n# ================================\n\ndef polinomioAdispersa(p: Polinomio[A]) -> list[tuple[int, A]]:\n    if esPolCero(p):\n        return []\n    return [(grado(p), coefLider(p))] + polinomioAdispersa(restoPol(p))\n\n# Propiedad de ser inversas\n# =========================\n\n# La primera propiedad es\n@given(ps=dispersaAleatoria())\ndef test_polinomioAdispersa_dispersaApolinomio(ps: list[tuple[int,\n                                                              int]]) -> None:\n    assert polinomioAdispersa(dispersaApolinomio(ps)) == ps\n\n# La segunda propiedad es\n@given(p=polinomioAleatorio())\ndef test_dispersaApolinomio_polinomioAdispersa(p: Polinomio[int]) -> None:\n    assert dispersaApolinomio(polinomioAdispersa(p)) == p\n\n# La comprobaci\u00f3n es\n#    > poetry run pytest -v Polinomios_Transformaciones_polinomios_dispersas.py\n#    test_dispersaApolinomio PASSED\n#    test_polinomioAdispersa_dispersaApolinomio PASSED\n#    test_dispersaApolinomio_polinomioAdispersa PASSED\n<\/pre>\n<p><a name=\"ej4\"><\/a><\/p>\n<h3>4. Coeficiente del t\u00e9rmino de grado k de un polinomio<\/h3>\n<p>Utilizando el <a href=\"https:\/\/bit.ly\/3KwqXYu\">tipo abstracto de datos de los polinomios<\/a> definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   coeficiente :: (Num a, Eq a) => Int -> Polinomio a -> a\n<\/pre>\n<p>tal que <code>coeficiente k p<\/code> es el coeficiente del t\u00e9rmino de grado <code>k<\/code> del polinomio <code>p<\/code>. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   \u03bb> ejPol = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\n   \u03bb> ejPol\n   x^5 + 5*x^2 + 4*x\n   \u03bb> coeficiente 2 ejPol\n   5\n   \u03bb> coeficiente 3 ejPol\n   0\n<\/pre>\n<p><b>Soluciones<\/b><\/p>\n<p>A continuaci\u00f3n se muestran las <a href=\"#haskell\">soluciones en Haskell<\/a> y las <a href=\"#python\">soluciones en Python<\/a>.<\/p>\n<p><a name=\"haskell\"><\/a><br \/>\n<b>Soluciones en Haskell<\/b><\/p>\n<pre lang=\"haskell\">\nimport TAD.Polinomio (Polinomio, coefLider, grado, restoPol,\n                      consPol, polCero)\n\ncoeficiente :: (Num a, Eq a) => Int -> Polinomio a -> a\ncoeficiente k p | k == n                 = coefLider p\n                | k > grado (restoPol p) = 0\n                | otherwise              = coeficiente k (restoPol p)\n  where n = grado p\n<\/pre>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom typing import TypeVar\n\nfrom src.TAD.Polinomio import (Polinomio, coefLider, consPol, grado, polCero,\n                               restoPol)\n\nA = TypeVar('A', int, float, complex)\n\ndef coeficiente(k: int, p: Polinomio[A]) -> A:\n    if k == grado(p):\n        return coefLider(p)\n    if k > grado(restoPol(p)):\n        return 0\n    return coeficiente(k, restoPol(p))\n<\/pre>\n<p><a name=\"ej5\"><\/a><\/p>\n<h3>5. Transformaciones entre polinomios y listas densas<\/h3>\n<p>Utilizando el <a href=\"https:\/\/bit.ly\/3KwqXYu\">tipo abstracto de datos de los polinomios<\/a> definir las funciones<\/p>\n<pre lang=\"text\">\n   densaApolinomio :: (Num a, Eq a) => [a] -> Polinomio a\n   polinomioAdensa :: (Num a, Eq a) => Polinomio a -> [a]\n<\/pre>\n<p>tales que<\/p>\n<ul>\n<li><code>densaApolinomio xs<\/code> es el polinomio cuya representaci\u00f3n densa es <code>xs<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     \u03bb> densaApolinomio [9,0,0,5,0,4,7]\n     9*x^6 + 5*x^3 + 4*x + 7\n<\/pre>\n<ul>\n<li><code>polinomioAdensa p<\/code> es la representaci\u00f3n densa del polinomio <code>p<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     \u03bb> ejPol = consPol 6 9 (consPol 3 5 (consPol 1 4 (consPol 0 7 polCero)))\n     \u03bb> ejPol\n     9*x^6 + 5*x^3 + 4*x + 7\n     \u03bb> polinomioAdensa ejPol\n     [9,0,0,5,0,4,7]\n<\/pre>\n<p>Comprobar con QuickCheck que ambas funciones son inversas.<\/p>\n<p><b>Soluciones<\/b><\/p>\n<p>A continuaci\u00f3n se muestran las <a href=\"#haskell\">soluciones en Haskell<\/a> y las <a href=\"#python\">soluciones en Python<\/a>.<\/p>\n<p><a name=\"haskell\"><\/a><br \/>\n<b>Soluciones en Haskell<\/b><\/p>\n<pre lang=\"haskell\">\nimport TAD.Polinomio (Polinomio, polCero, esPolCero, consPol, grado,\n                      coefLider, restoPol)\nimport Polinomios_Transformaciones_dispersa_y_densa (densaAdispersa,\n                                                     dispersaAdensa)\nimport Polinomios_Transformaciones_polinomios_dispersas (dispersaApolinomio,\n                                                         polinomioAdispersa)\nimport Polinomios_Coeficiente (coeficiente)\nimport Data.List (sort, nub)\nimport Test.QuickCheck\n\n-- 1\u00aa definici\u00f3n de densaApolinomio\n-- ================================\n\ndensaApolinomio :: (Num a, Eq a) => [a] -> Polinomio a\ndensaApolinomio []     = polCero\ndensaApolinomio (x:xs) = consPol (length xs) x (densaApolinomio xs)\n\n-- 2\u00aa definici\u00f3n de densaApolinomio\n-- ================================\n\ndensaApolinomio2 :: (Num a, Eq a) => [a] -> Polinomio a\ndensaApolinomio2 = dispersaApolinomio . densaAdispersa\n\n-- La funci\u00f3n densaAdispersa est\u00e1 definida en el ejercicio\n-- \"Transformaciones entre las representaciones dispersa y densa\" que se\n-- encuentra en https:\/\/bit.ly\/3GTyIqe\n\n-- La funci\u00f3n dispersaApolinomio se encuentra en el ejercicio\n-- \"Transformaciones entre polinomios y listas dispersas\" que se\n-- encuentra en https:\/\/bit.ly\/41GgQaB\n\n-- Comprobaci\u00f3n de equivalencia de densaApolinomio\n-- ===============================================\n\n-- La propiedad es\nprop_densaApolinomio :: [Int] -> Bool\nprop_densaApolinomio xs =\n  densaApolinomio xs == densaApolinomio2 xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_densaApolinomio\n--    +++ OK, passed 100 tests.\n\n-- 1\u00aa definici\u00f3n de polinomioAdensa\n-- ================================\n\npolinomioAdensa :: (Num a, Eq a) => Polinomio a -> [a]\npolinomioAdensa p\n  | esPolCero p = []\n  | otherwise   = [coeficiente k p | k <- [n,n-1..0]]\n  where n = grado p\n\n-- La funci\u00f3n coeficiente est\u00e1 definida en el ejercicio\n-- \"Coeficiente del t\u00e9rmino de grado k\" que se encuentra en\n-- https:\/\/bit.ly\/413l3oQ\n\n-- 2\u00aa definici\u00f3n de polinomioAdensa\n-- ================================\n\npolinomioAdensa2 :: (Num a, Eq a) => Polinomio a -> [a]\npolinomioAdensa2 = dispersaAdensa . polinomioAdispersa\n\n-- La funci\u00f3n dispersaAdensa est\u00e1 definida en el ejercicio\n-- \"Transformaciones entre las representaciones dispersa y densa\" que se\n-- encuentra en https:\/\/bit.ly\/3GTyIqe\n\n-- La funci\u00f3n polinomioAdispersa se encuentra en el ejercicio\n-- \"Transformaciones entre polinomios y listas dispersas\" que se\n-- encuentra en https:\/\/bit.ly\/41GgQaB\n\n-- Comprobaci\u00f3n de equivalencia de polinomioAdensa\n-- ===============================================\n\n-- La propiedad es\nprop_polinomioAdensa :: Polinomio Int -> Bool\nprop_polinomioAdensa p =\n  polinomioAdensa p == polinomioAdensa2 p\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_polinomioAdensa\n--    +++ OK, passed 100 tests.\n\n-- Propiedades de inversa\n-- ======================\n\n-- La primera propiedad es\nprop_polinomioAdensa_densaApolinomio :: [Int] -> Bool\nprop_polinomioAdensa_densaApolinomio xs =\n  polinomioAdensa (densaApolinomio xs') == xs'\n  where xs' = dropWhile (== 0) xs\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_polinomioAdensa_densaApolinomio\n--    +++ OK, passed 100 tests.\n\n-- La segunda propiedad es\nprop_densaApolinomio_polinomioAdensa :: Polinomio Int -> Bool\nprop_densaApolinomio_polinomioAdensa p =\n   densaApolinomio (polinomioAdensa p) == p\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_densaApolinomio_polinomioAdensa\n--    +++ OK, passed 100 tests.\n<\/pre>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom typing import TypeVar\n\nfrom hypothesis import given\n\nfrom src.Polinomios_Coeficiente import coeficiente\nfrom src.Polinomios_Transformaciones_dispersa_y_densa import (densaAdispersa,\n                                                              densaAleatoria,\n                                                              dispersaAdensa)\nfrom src.Polinomios_Transformaciones_polinomios_dispersas import (\n    dispersaApolinomio, polinomioAdispersa)\nfrom src.TAD.Polinomio import (Polinomio, coefLider, consPol, esPolCero, grado,\n                               polCero, polinomioAleatorio, restoPol)\n\nA = TypeVar('A', int, float, complex)\n\n# 1\u00aa definici\u00f3n de densaApolinomio\n# ================================\n\ndef densaApolinomio(xs: list[A]) -> Polinomio[A]:\n    if not xs:\n        return polCero()\n    return consPol(len(xs[1:]), xs[0], densaApolinomio(xs[1:]))\n\n# 2\u00aa definici\u00f3n de densaApolinomio\n# ================================\n\ndef densaApolinomio2(xs: list[A]) -> Polinomio[A]:\n    return dispersaApolinomio(densaAdispersa(xs))\n\n# La funci\u00f3n densaAdispersa est\u00e1 definida en el ejercicio\n# \"Transformaciones entre las representaciones dispersa y densa\" que se\n# encuentra en https:\/\/bit.ly\/3GTyIqe\n\n# La funci\u00f3n dispersaApolinomio se encuentra en el ejercicio\n# \"Transformaciones entre polinomios y listas dispersas\" que se\n# encuentra en https:\/\/bit.ly\/41GgQaB\n\n# Comprobaci\u00f3n de equivalencia de densaApolinomio\n# ===============================================\n\n# La propiedad es\n@given(xs=densaAleatoria())\ndef test_densaApolinomio(xs: list[int]) -> None:\n    assert densaApolinomio(xs) == densaApolinomio2(xs)\n\n# La funci\u00f3n densaAleatoria est\u00e1 definida en el ejercicio\n# \"Transformaciones entre las representaciones dispersa y densa\" que se\n# encuentra en https:\/\/bit.ly\/3GTyIqe\n\n# 1\u00aa definici\u00f3n de polinomioAdensa\n# ================================\n\ndef polinomioAdensa(p: Polinomio[A]) -> list[A]:\n    if esPolCero(p):\n        return []\n    n = grado(p)\n    return [coeficiente(k, p) for k in range(n, -1, -1)]\n\n# La funci\u00f3n coeficiente est\u00e1 definida en el ejercicio\n# \"Coeficiente del t\u00e9rmino de grado k\" que se encuentra en\n# https:\/\/bit.ly\/413l3oQ\n\n# 2\u00aa definici\u00f3n de polinomioAdensa\n# ================================\n\ndef polinomioAdensa2(p: Polinomio[A]) -> list[A]:\n    return dispersaAdensa(polinomioAdispersa(p))\n\n# La funci\u00f3n dispersaAdensa est\u00e1 definida en el ejercicio\n# \"Transformaciones entre las representaciones dispersa y densa\" que se\n# encuentra en https:\/\/bit.ly\/3GTyIqe\n\n# La funci\u00f3n polinomioAdispersa se encuentra en el ejercicio\n# \"Transformaciones entre polinomios y listas dispersas\" que se\n# encuentra en https:\/\/bit.ly\/41GgQaB\n\n# Comprobaci\u00f3n de equivalencia de polinomioAdensa\n# ===============================================\n\n# La propiedad es\n@given(p=polinomioAleatorio())\ndef test_polinomioAdensa(p: Polinomio[int]) -> None:\n    assert polinomioAdensa(p) == polinomioAdensa2(p)\n\n# Propiedades de inversa\n# ======================\n\n# La primera propiedad es\n@given(xs=densaAleatoria())\ndef test_polinomioAdensa_densaApolinomio(xs: list[int]) -> None:\n    assert polinomioAdensa(densaApolinomio(xs)) == xs\n\n# La segunda propiedad es\n@given(p=polinomioAleatorio())\ndef test_densaApolinomio_polinomioAdensa(p: Polinomio[int]) -> None:\n    assert densaApolinomio(polinomioAdensa(p)) == p\n\n# La comprobaci\u00f3n es\n#    > poetry run pytest -v Polinomios_Transformaciones_polinomios_densas.py\n#    test_densaApolinomio PASSED\n#    test_polinomioAdensa PASSED\n#    test_polinomioAdensa_densaApolinomio PASSED\n#    test_densaApolinomio_polinomioAdensa PASSED\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Esta semana he publicado en Exercitium las soluciones de los siguientes problemas: 1. El tipo abstracto de datos de los polinomios 2. Transformaciones entre las representaciones dispersa y densa de polinomios 3. Transformaciones entre polinomios y listas dispersas 4. Coeficiente del t\u00e9rmino de grado k de un polinomio 5. Transformaciones entre polinomios y listas densas&#8230;<\/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":[1],"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\/7926"}],"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=7926"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7926\/revisions"}],"predecessor-version":[{"id":7927,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7926\/revisions\/7927"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=7926"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=7926"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=7926"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}