{"id":4198,"date":"2014-03-21T17:19:56","date_gmt":"2014-03-21T16:19:56","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=4198"},"modified":"2014-03-26T07:20:57","modified_gmt":"2014-03-26T06:20:57","slug":"i1m2013-4o-examen-de-programacion-con-haskell","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/i1m2013-4o-examen-de-programacion-con-haskell\/","title":{"rendered":"I1M2013: 4\u00ba examen de programaci\u00f3n con Haskell"},"content":{"rendered":"<p>En la clase de hoy del curso <a href=\"http:\/\/www.cs.us.es\/~jalonso\/cursos\/i1m-13\">Inform\u00e1tica (de 1\u00ba de Grado en Matem\u00e1ticas)<\/a> se ha realizado el 4\u00ba examen del curso. Adem\u00e1s, durante esta semana se han realizado los ex\u00e1menes de los otros grupos. A continuaci\u00f3n se muestran las soluciones de dichos ex\u00e1menes.<\/p>\n<p>Las soluciones del examen del grupo 3 son<br \/>\n<!--more--><\/p>\n<pre lang=\"haskell\">\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1. [2.5 puntos] Definir la funci\u00f3n\r\n--    interpretaciones :: [a] -> [[(a,Int)]]\r\n-- tal que (interpretaciones xs) es la lista de las interpretaciones\r\n-- sobre la lista de las variables proposicionales xs sobre los valores\r\n-- de verdad 0 y 1. Por ejemplo,\r\n--    ghci> interpretaciones \"A\"\r\n--    [[('A',0)],[('A',1)]]\r\n--    ghci> interpretaciones \"AB\"\r\n--    [[('A',0),('B',0)],[('A',0),('B',1)],\r\n--     [('A',1),('B',0)],[('A',1),('B',1)]]\r\n--    ghci> interpretaciones \"ABC\"\r\n--    [[('A',0),('B',0),('C',0)],[('A',0),('B',0),('C',1)],\r\n--     [('A',0),('B',1),('C',0)],[('A',0),('B',1),('C',1)],\r\n--     [('A',1),('B',0),('C',0)],[('A',1),('B',0),('C',1)],\r\n--     [('A',1),('B',1),('C',0)],[('A',1),('B',1),('C',1)]]\r\n-- ---------------------------------------------------------------------\r\n\r\ninterpretaciones :: [a] -> [[(a,Int)]]\r\ninterpretaciones [] = [[]]\r\ninterpretaciones (x:xs) = \r\n    [(x,0):i | i <-is] ++ [(x,1):i | i <- is]\r\n    where is = interpretaciones xs\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 2. [2.5 puntos] Los n\u00fameros de Hamming forman una sucesi\u00f3n\r\n-- estrictamente creciente de n\u00fameros que cumplen las siguientes\r\n-- condiciones:  \r\n--    * El n\u00famero 1 est\u00e1 en la sucesi\u00f3n.\r\n--    * Si x est\u00e1 en la sucesi\u00f3n, entonces 2x, 3x y 5x tambi\u00e9n est\u00e1n.\r\n--    * Ning\u00fan otro n\u00famero est\u00e1 en la sucesi\u00f3n. \r\n-- Los primeros t\u00e9rminos de la sucesi\u00f3n de Hamming son\r\n--    1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, ...\r\n--\r\n-- Definir la funci\u00f3n\r\n--    siguienteHamming :: Int -> Int\r\n-- tal que (siguienteHamming x) es el menor t\u00e9rmino de la sucesi\u00f3n de\r\n-- Hamming mayor que x. Por ejemplo,\r\n--    siguienteHamming 10  ==  12\r\n--    siguienteHamming 12  ==  15\r\n--    siguienteHamming 15  ==  16\r\n-- ---------------------------------------------------------------------\r\n\r\nsiguienteHamming :: Int -> Int\r\nsiguienteHamming x = head (dropWhile (<=x) hamming)\r\n\r\n-- hamming es la sucesi\u00f3n de Hamming. Por ejemplo,\r\n--    take 12 hamming == [1,2,3,4,5,6,8,9,10,12,15,16]\r\nhamming :: [Int]\r\nhamming = 1 : mezcla3 [2*i | i <- hamming]  \r\n                      [3*i | i <- hamming]  \r\n                      [5*i | i <- hamming]  \r\n\r\n-- (mezcla3 xs ys zs) es la lista obtenida mezclando las listas\r\n-- ordenadas xs, ys y zs y eliminando los elementos duplicados. Por\r\n-- ejemplo, \r\n--    ghci> mezcla3 [2,4,6,8,10] [3,6,9,12] [5,10]\r\n--    [2,3,4,5,6,8,9,10,12]\r\nmezcla3 :: [Int] -> [Int] -> [Int] -> [Int]\r\nmezcla3 xs ys zs = mezcla2 xs (mezcla2 ys zs)  \r\n\r\n-- (mezcla2 xs ys zs) es la lista obtenida mezclando las listas\r\n-- ordenadas xs e ys y eliminando los elementos duplicados. Por ejemplo,\r\n--    ghci> mezcla2 [2,4,6,8,10,12] [3,6,9,12]\r\n--    [2,3,4,6,8,9,10,12]\r\nmezcla2 :: [Int] -> [Int] -> [Int]\r\nmezcla2 p@(x:xs) q@(y:ys) | x < y     = x:mezcla2 xs q\r\n                          | x > y     = y:mezcla2 p  ys  \r\n                          | otherwise = x:mezcla2 xs ys\r\nmezcla2 []       ys                   = ys\r\nmezcla2 xs       []                   = xs\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3. [2.5 puntos] Las operaciones de suma, resta y\r\n-- multiplicaci\u00f3n se pueden representar mediante el siguiente tipo de\r\n-- datos \r\n--    data Op = S | R | M\r\n-- La expresiones aritm\u00e9ticas con dichas operaciones se pueden\r\n-- representar mediante el siguiente tipo de dato algebraico\r\n--    data Expr = N Int | A Op Expr Expr\r\n-- Por ejemplo, la expresi\u00f3n\r\n--    (7-3)+(2*5)\r\n-- se representa por\r\n--    A S (A R (N 7) (N 3)) (A M (N 2) (N 5))\r\n--\r\n-- Definir la funci\u00f3n\r\n--    valor :: Expr -> Int\r\n-- tal que (valor e) es el valor de la expresi\u00f3n e. Por ejemplo,\r\n--    valor (A S (A R (N 7) (N 3)) (A M (N 2) (N 5)))  ==  14\r\n--    valor (A M (A R (N 7) (N 3)) (A S (N 2) (N 5)))  ==  28\r\n-- ---------------------------------------------------------------------\r\n\r\ndata Op = S | R | M\r\n\r\ndata Expr = N Int | A Op Expr Expr\r\n\r\nvalor :: Expr -> Int\r\nvalor (N x) = x\r\nvalor (A o e1 e2) = aplica o (valor e1) (valor e2)\r\n\r\naplica :: Op -> Int -> Int -> Int\r\naplica S x y = x+y\r\naplica R x y = x-y\r\naplica M x y = x*y\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4. [2.5 puntos] Los polinomios con coeficientes naturales\r\n-- se pueden representar mediante el siguiente tipo algebraico\r\n--    data Polinomio = O | C Int Int Polinomio\r\n-- Por ejemplo, el polinomio 2x^5 + 4x^3 + 2x se representa por\r\n--    C 2 5 (C 4 3 (C 2 1 O))\r\n-- Tambi\u00e9n se pueden representar mediante listas no crecientes de\r\n-- naturales. Por ejemplo, el polinomio 2x^5 + 4x^3 + 2x se representa\r\n-- por \r\n--    [5,5,3,3,3,3,1,1]\r\n-- en la lista anterior, el n\u00famero de veces que aparece cada n\u00famero n es\r\n-- igual al coeficiente de x^n en el polinomio.\r\n-- \r\n-- Definir la funci\u00f3n\r\n--    transformaPol :: Polinomio -> [Int]\r\n-- tal que (transformaPol p) es el polinomio obtenido transformado el\r\n-- polinomio p de la primera representaci\u00f3n a la segunda. Por ejemplo, \r\n--    transformaPol (C 2 5 (C 4 3 (C 2 1 O)))  ==  [5,5,3,3,3,3,1,1]\r\n--    transformaPol (C 2 100 (C 3 1 O))        ==  [100,100,1,1,1]\r\n-- ---------------------------------------------------------------------\r\n\r\ndata Polinomio = O | C Int Int Polinomio\r\n\r\ntransformaPol :: Polinomio -> [Int]\r\ntransformaPol O         = []\r\ntransformaPol (C a n p) = replicate a n ++ transformaPol p\r\n<\/pre>\n<p>Las soluciones del examen del grupo 1 (impartido por Mar\u00eda J. Hidalgo) son<\/p>\n<pre lang=\"haskell\">\r\n-- ---------------------------------------------------------------------\r\n-- \u00a7 Librer\u00edas auxiliares                                             --\r\n-- ---------------------------------------------------------------------\r\n\r\nimport Test.QuickCheck\r\nimport Data.Ratio\r\nimport Data.List\r\nimport PolOperaciones\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.1. Consideremos la sucesi\u00f3n siguiente\r\n--     a0 = 1\r\n--     a1 = 1\r\n--     an = 7*a(n-1) - a(n-2) - 2\r\n-- \r\n-- Definir, por recursi\u00f3n, la funci\u00f3n\r\n--     suc :: Integer -> Integer  \r\n-- tal que (suc n) es el n-\u00e9simo t\u00e9rmino de la sucesi\u00f3n anterior. Por\r\n-- ejemplo, \r\n--     suc 1 == 1\r\n--     suc 4 == 169\r\n--     suc 8 == 372100\r\n-- Por ejemplo,\r\n--    ghci> [suc n | n <-[0..10]]\r\n--    [1,1,4,25,169,1156,7921,54289,372100,2550409,17480761]\r\n-- ---------------------------------------------------------------------\r\n\r\nsuc :: Integer -> Integer  \r\nsuc 0 = 1\r\nsuc 1 = 1\r\nsuc n = 7*(suc (n-1)) - (suc (n-2)) - 2\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.2. Definir, usando evaluaci\u00f3n perezosa. la funci\u00f3n\r\n--     suc' :: Integer -> Integer  \r\n-- tal que (suc n) es el n-\u00e9simo t\u00e9rmino de la sucesi\u00f3n anterior. Por\r\n-- ejemplo, \r\n--     suc 1 == 1\r\n--     suc 4 == 169\r\n--     suc 8 == 372100\r\n-- Por ejemplo,\r\n--    ghci> [suc n | n <-[0..10]]\r\n--    [1,1,4,25,169,1156,7921,54289,372100,2550409,17480761]\r\n--    ghci> suc' 30\r\n--    915317035111995882133681\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La sucesi\u00f3n es\r\nsucesion:: [Integer]\r\nsucesion = 1:1:zipWith f (tail sucesion) sucesion \r\n    where f x y = 7*x-y-2\r\n\r\n-- Por ejemplo, el c\u00e1lculo de los 4 primeros t\u00e9rminos es\r\n--    take 4 sucesion\r\n--    = take 4 (1:1:zipWith f (tail sucesion) sucesion)\r\n--    = 1:take 3 (1:zipWith f (tail sucesion) sucesion)\r\n--    = 1:1:take 2 (zipWith f (tail sucesion) sucesion)\r\n--    = 1:1:take 2 (zipWith f (1:R2) (1:1:R2))\r\n--    = 1:1:take 2 (4:zipWith f R2 (1:R2))\r\n--    = 1:1:4:take 1 (zipWith f (4:R3) (1:4:R3))\r\n--    = 1:1:4:take 1 (25:zipWith f R3 (4:R3))\r\n--    = 1:1:4:25:take 0 (25:zipWith f R3 (4:R3))\r\n--    = 1:1:4:25:[]\r\n--    = [1,1,4,25]\r\n        \r\nsuc' :: Integer -> Integer        \r\nsuc' n = sucesion `genericIndex` n        \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.3. Calcular el t\u00e9rmino 100 de la sucesi\u00f3n anterior.\r\n-- ---------------------------------------------------------------------\r\n\r\n-- El c\u00e1lculo es\r\n--    ghci> suc' 100\r\n--    30068434349082593880211806294947596752920546625789181082505523070321286807046578601\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.4. Comprobar que los primeros 30 t\u00e9rminos de la sucesi\u00f3n\r\n-- son cuadrados perfectos.\r\n-- ---------------------------------------------------------------------\r\n\r\nesCuadrado :: (Integral a) => a -> Bool\r\nesCuadrado n = y*y == n\r\n    where y = floor (sqrt (fromIntegral n))\r\n\r\n-- La comprobaci\u00f3n es        \r\n--    ghci> and [esCuadrado (suc' n) | n <-[0..30]]\r\n--    True\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 2. Consideremos los \u00e1rboles binarios definidos por el tipo\r\n-- siguiente: \r\n--    data Arbol t = Hoja t \r\n--               | Nodo (Arbol t) t (Arbol t)\r\n--               deriving (Show, Eq)\r\n-- y el siguiente ejemplo de \u00e1rbol   \r\n--    ejArbol :: Arbol Int\r\n--    ejArbol = Nodo (Nodo (Hoja 1) 3 (Hoja 4)) \r\n--                   5 \r\n--                   (Nodo (Hoja 6) 7 (Hoja 9))\r\n-- \r\n-- Definir la funci\u00f3n \r\n--    transforma :: (t -> Bool) -> Arbol t -> Arbol (Maybe t)\r\n-- tal que (transforma p a) es el \u00e1rbol con la misma estructura que a,\r\n-- en el que cada elemento x que verifica el predicado p se sustituye por\r\n-- (Just x) y los que no lo verifican se sustituyen por Nothing. Por\r\n-- ejemplo,\r\n--    ghci> transforma even ejArbol\r\n--    Nodo (Nodo (Hoja Nothing) Nothing (Hoja (Just 4))) \r\n--         Nothing \r\n--         (Nodo (Hoja (Just 6)) Nothing (Hoja Nothing))\r\n-- ---------------------------------------------------------------------\r\n\r\ndata Arbol t = Hoja t \r\n           | Nodo (Arbol t) t (Arbol t)\r\n           deriving (Show, Eq)\r\n\r\nejArbol :: Arbol Int\r\nejArbol = Nodo (Nodo (Hoja 1) 3 (Hoja 4)) \r\n               5 \r\n               (Nodo (Hoja 6) 7 (Hoja 9))\r\n\r\ntransforma :: (t -> Bool) -> Arbol t -> Arbol (Maybe t)\r\ntransforma p (Hoja r) | p r       = Hoja (Just r)\r\n                      | otherwise = Hoja Nothing\r\ntransforma p (Nodo i r d) \r\n    | p r       = Nodo (transforma p i) (Just r) (transforma p d)                                    \r\n    | otherwise = Nodo (transforma p i) Nothing (transforma p d)                                    \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3. El m\u00e9todo de la bisecci\u00f3n para calcular un cero de una\r\n-- funci\u00f3n en el intervalo [a,b] se basa en el Teorema de Bolzano: \"Si\r\n-- f(x) es una funci\u00f3n continua en el intervalo [a, b], y si, adem\u00e1s, en\r\n-- los  extremos del intervalo la funci\u00f3n f(x) toma valores de signo\r\n-- opuesto (f(a) * f(b) < 0), entonces existe al menos un valor c en (a,\r\n-- b) para el que f(c) = 0\".\r\n-- \r\n-- La idea es tomar el punto medio del intervalo c = (a+b)\/2 y\r\n-- considerar los siguientes casos:\r\n-- (*) Si f(c) ~= 0, hemos encontrado una aproximaci\u00f3n del punto que\r\n--     anula f en el intervalo con un error aceptable.\r\n-- (*) Si f(c) tiene signo distinto de f(a), repetir el proceso en el\r\n--     intervalo [a,c].\r\n-- (*) Si no, repetir el proceso en el intervalo [c,b].\r\n-- \r\n-- Definir la funci\u00f3n\r\n--    ceroBiseccionE :: (Double -> Double) ->\r\n--                      Double -> Double -> Double -> Double\r\n-- tal que (ceroBiseccionE f a b e) calcule una aproximaci\u00f3n del punto \r\n-- del intervalo [a,b] en el que se anula la funci\u00f3n f, con un error\r\n-- menor que e, aplicando el m\u00e9todo de la bisecci\u00f3n. Por ejemplo,\r\n-- si f1 y f2 son las funciones definidas por\r\n--    f1 x = 2 - x\r\n--    f2 x = x^2 - 3 \r\n-- entonces\r\n--    ceroBiseccionE f1 0 3 0.0001     == 2.00006103515625\r\n--    ceroBiseccionE f2 0 2 0.0001     == 1.7320556640625\r\n--    ceroBiseccionE f2 (-2) 2 0.00001 == -1.732048\r\n--    ceroBiseccionE cos 0 2 0.0001    == -1.7320480346679688\r\n-- ---------------------------------------------------------------------\r\n\r\nf1 x = 2 - x\r\nf2 x = x^2 - 3 \r\n\r\nceroBiseccionE :: (Double -> Double) -> \r\n                  Double -> Double -> Double -> Double\r\nceroBiseccionE f a b e = aux a b\r\n    where aux c d | aceptable m     = m\r\n                  | (f c)*(f m) < 0 = aux c m\r\n                  | otherwise       = aux m d\r\n              where m = (c+d)\/2\r\n                    aceptable x = abs (f x) < e \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4.1. Los polinomios de Fibonacci se definen como sigue\r\n--    P_0 = 0                    \r\n--    P_1 = 1                    \r\n--    P_n = x*P_(n-1) + P_(n-2)                    \r\n--                    \r\n-- Definir la funci\u00f3n \r\n--    polFibonnaci :: Integer -> Polinomio Rational\r\n-- tal que (polFibonnaci n) es el n-\u00e9simo polinomio de Fibonacci. Por\r\n-- ejemplo, \r\n--    polFibonnaci 2 == 1 % 1*x\r\n--    polFibonnaci 3 == x^2 + 1 % 1\r\n--    polFibonnaci 4 == x^3 + 2 % 1*x\r\n--    polFibonnaci 5 == x^4 + 3 % 1*x^2 + 1 % 1\r\n-- ---------------------------------------------------------------------   \r\n                    \r\n-- 1\u00aa soluci\u00f3n (por recursi\u00f3n)\r\npolFibonnaci :: Integer -> Polinomio Rational\r\npolFibonnaci 0 = polCero\r\npolFibonnaci 1 = polUnidad\r\npolFibonnaci n = \r\n    sumaPol (multPol (creaPolDispersa [1,0]) (polFibonnaci (n-1)))\r\n            (polFibonnaci (n-2))\r\n\r\n-- 2\u00aa soluci\u00f3n (evaluaci\u00f3n perezosa)\r\npolFibonnaciP :: Integer -> Polinomio Rational\r\npolFibonnaciP n = sucPolinomiosFibonacci `genericIndex` n\r\n\r\nsucPolinomiosFibonacci :: [Polinomio Rational]\r\nsucPolinomiosFibonacci =\r\n    polCero:polUnidad:zipWith f (tail sucPolinomiosFibonacci)\r\n                                sucPolinomiosFibonacci\r\n        where f p q = sumaPol (multPol (creaPolDispersa [1,0]) p) q\r\n    \r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4.2. Comprobar que P_2 divide a los polinomios de Fibonacci\r\n-- de \u00edndice par hasta n = 20.\r\n-- ---------------------------------------------------------------------\r\n\r\ndivide :: (Fractional a, Eq a) => Polinomio a -> Polinomio a -> Bool\r\ndivide p q = esPolCero (resto q p)\r\n\r\n-- La comprobaci\u00f3n es\r\n-- ghci> and [divide (polFibonnaciP 2) (polFibonnaciP (2*k)) | k <- [2..20]]\r\n-- True\r\n<\/pre>\n<p>Para el cuarto ejercicio se usan la librer\u00eda del tipo abstracto de polinomios (PolRepTDA.hs)<\/p>\n<pre lang=\"haskell\">\r\nmodule PolRepTDA\r\n  ( Polinomio,\r\n    polCero,   -- Polinomio a                                         \r\n    esPolCero, -- Polinomio a -> Bool                       \r\n    consPol,   -- (Num a, Eq a)) => Int -> a -> Polinomio a -> Polinomio a   \r\n    grado,     -- Polinomio a -> Int                                  \r\n    coefLider, -- Num t => Polinomio t -> t                           \r\n    restoPol   -- Polinomio t -> Polinomio t                          \r\n  ) where\r\n\r\n-- ---------------------------------------------------------------------\r\n-- TAD de los polinomios mediante un tipo de dato algebraico.         --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- Representamos un polinomio mediante los constructores ConsPol y\r\n-- PolCero. Por ejemplo, el polinomio \r\n--    6x^4 -5x^2 + 4x -7 \r\n-- se representa por \r\n--    ConsPol 4 6 (ConsPol 2 (-5) (ConsPol 1 4 (ConsPol 0 (-7) PolCero)))\r\n\r\ndata Polinomio a = PolCero \r\n                 | ConsPol Int a (Polinomio a)\r\n                 deriving Eq\r\n             \r\n-- ---------------------------------------------------------------------\r\n-- Escritura de los polinomios                                        --\r\n-- ---------------------------------------------------------------------\r\n\r\ninstance (Num a, Show a, Eq a) => Show (Polinomio a) where\r\n    show PolCero               = \"0\"\r\n    show (ConsPol 0 b PolCero) = show b\r\n    show (ConsPol 0 b p)       = concat [show b, \" + \", show p] \r\n    show (ConsPol 1 b PolCero) = concat [show b, \"*x\"]\r\n    show (ConsPol 1 b p)       = concat [show b, \"*x + \", show p] \r\n    show (ConsPol n 1 PolCero) = concat [\"x^\", show n] \r\n    show (ConsPol n b PolCero) = concat [show b, \"*x^\", show n] \r\n    show (ConsPol n 1 p)       = concat [\"x^\", show n, \" + \", show p] \r\n    show (ConsPol n b p)       = concat [show b, \"*x^\", show n, \" + \", show p] \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejemplos de polinomios                                             --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- Ejemplos de polinomios con coeficientes enteros:\r\nejPol1, ejPol2, ejPol3:: Polinomio Int\r\nejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\r\nejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\r\nejPol3 = consPol 4 6 (consPol 1 2 polCero)\r\n\r\n-- Comprobaci\u00f3n de escritura:\r\n--    > ejPol1\r\n--    3*x^4 + -5*x^2 + 3\r\n--    > ejPol2\r\n--    x^5 + 5*x^2 + 4*x\r\n--    > ejPol3\r\n--    6*x^4 + 2*x\r\n\r\n-- Ejemplos de polinomios con coeficientes reales:\r\nejPol5, ejPol6, ejPol7:: Polinomio Float\r\nejPol5 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\r\nejPol6 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\r\nejPol7 = consPol 1 2 (consPol 4 6 polCero)\r\n\r\n-- Comprobaci\u00f3n de escritura:\r\n--    > ejPol5\r\n--    3.0*x^4 + -5.0*x^2 + 3.0\r\n--    > ejPol6\r\n--    x^5 + 5.0*x^2 + 4.0*x\r\n--    > ejPol7\r\n--    6.0*x^4 + 2.0*x\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Implementaci\u00f3n de la especificaci\u00f3n                                --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- polCero es el polinomio cero. Por ejemplo,\r\n--    > polCero\r\n--    0\r\npolCero :: Polinomio a\r\npolCero = PolCero\r\n\r\n-- (esPolCero p) se verifica si p es el polinomio cero. Por ejemplo,\r\n--    esPolCero polCero  ==  True\r\n--    esPolCero ejPol1   ==  False\r\nesPolCero :: Polinomio a -> Bool\r\nesPolCero PolCero = True\r\nesPolCero _       = False\r\n\r\n-- (consPol n b p) es el polinomio bx^n+p. Por ejemplo,\r\n--    ejPol2               ==  x^5 + 5*x^2 + 4*x\r\n--    consPol 3 0 ejPol2   ==  x^5 + 5*x^2 + 4*x\r\n--    consPol 3 2 polCero  ==  2*x^3\r\n--    consPol 6 7 ejPol2   ==  7*x^6 + x^5 + 5*x^2 + 4*x\r\n--    consPol 4 7 ejPol2   ==  x^5 + 7*x^4 + 5*x^2 + 4*x\r\n--    consPol 5 7 ejPol2   ==  8*x^5 + 5*x^2 + 4*x\r\nconsPol :: (Num a, Eq a) => Int -> a -> Polinomio a -> Polinomio a  \r\nconsPol _ 0 p = p\r\nconsPol n b PolCero = ConsPol n b PolCero\r\nconsPol n b (ConsPol m c p) \r\n    | n > m      = ConsPol n b (ConsPol m c p)\r\n    | n < m      = ConsPol m c (consPol n b p)\r\n    | b+c == 0   = p\r\n    | otherwise  = ConsPol n (b+c) p\r\n\r\n-- (grado p) es el grado del polinomio p. Por ejemplo,\r\n--    ejPol3        ==  6*x^4 + 2*x\r\n--    grado ejPol3  ==  4\r\ngrado:: Polinomio a -> Int\r\ngrado PolCero         = 0\r\ngrado (ConsPol n _ _) = n\r\n\r\n-- (coefLider p) es el coeficiente l\u00edder del polinomio p. Por ejemplo,\r\n--    ejPol3            ==  6*x^4 + 2*x\r\n--    coefLider ejPol3  ==  6\r\ncoefLider:: Num t => Polinomio t -> t\r\ncoefLider PolCero         = 0\r\ncoefLider (ConsPol _ b _) = b\r\n\r\n-- (restoPol p) es el resto del polinomio p. Por ejemplo,\r\n--    ejPol3           ==  6*x^4 + 2*x\r\n--    restoPol ejPol3  ==  2*x\r\n--    ejPol2           ==  x^5 + 5*x^2 + 4*x\r\n--    restoPol ejPol2  ==  5*x^2 + 4*x\r\nrestoPol :: Polinomio t -> Polinomio t\r\nrestoPol PolCero         = PolCero\r\nrestoPol (ConsPol _ _ p) = p\r\n<\/pre>\n<p>y la de operaciones con polinomios (PolOperaciones.hs)<\/p>\n<pre lang=\"haskell\">\r\nmodule PolOperaciones (module Pol, module PolOperaciones) where\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Importaci\u00f3n de librer\u00edas                                           --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- Nota: Hay que elegir una implementaci\u00f3n del TAD de los polinomios.\r\nimport PolRepTDA as Pol\r\n-- import PolRepDispersa as Pol\r\n-- import PolRepDensa as Pol\r\n\r\nimport Test.QuickCheck\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejemplos                                                           --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- Ejemplos de polinomios con coeficientes enteros:\r\nejPol1, ejPol2, ejPol3, ejTerm:: Polinomio Int\r\nejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero))\r\nejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero))\r\nejPol3 = consPol 4 6 (consPol 1 2 polCero)\r\nejTerm = consPol 1 4 polCero\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Generador de polinomios                                            --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (genPol n) es un generador de polinomios. Por ejemplo,\r\n--    ghci> sample (genPol 1)\r\n--    7*x^9 + 9*x^8 + 10*x^7 + -14*x^5 + -15*x^2 + -10\r\n--    -4*x^8 + 2*x\r\n--    -8*x^9 + 4*x^8 + 2*x^6 + 4*x^5 + -6*x^4 + 5*x^2 + -8*x\r\n--    -9*x^9 + x^5 + -7\r\n--    8*x^10 + -9*x^7 + 7*x^6 + 9*x^5 + 10*x^3 + -1*x^2\r\n--    7*x^10 + 5*x^9 + -5\r\n--    -8*x^10 + -7\r\n--    -5*x\r\n--    5*x^10 + 4*x^4 + -3\r\n--    3*x^3 + -4\r\n--    10*x\r\ngenPol :: (Arbitrary a, Num a, Eq a) => Int -> Gen (Polinomio a)\r\ngenPol 0 = return polCero\r\ngenPol n = do n <- choose (0,10)\r\n              b <- arbitrary\r\n              p <- genPol (div n 2)\r\n              return (consPol n b p) \r\n\r\ninstance (Arbitrary a, Num a, Eq a) => Arbitrary (Polinomio a) where\r\n    arbitrary = sized genPol\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Funciones sobre t\u00e9rminos                                           --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (creaTermino n a) es el t\u00e9rmino a*x^n. Por ejemplo, \r\n--    creaTermino 2 5  ==  5*x^2\r\ncreaTermino:: (Num t, Eq t) => Int -> t -> Polinomio t\r\ncreaTermino n a = consPol n a polCero\r\n\r\n-- (termLider p) es el t\u00e9rmino l\u00edder del polinomio p. Por ejemplo,\r\n--    ejPol2            ==  x^5 + 5*x^2 + 4*x\r\n--    termLider ejPol2  ==  x^5\r\ntermLider:: (Num t, Eq t) => Polinomio t -> Polinomio t\r\ntermLider p = creaTermino (grado p) (coefLider p)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Suma de polinomios                                                 --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (sumaPol p q) es la suma de los polinomios p y q. Por ejemplo, \r\n--    ejPol1                 ==  3*x^4 + -5*x^2 + 3\r\n--    ejPol2                 ==  x^5 + 5*x^2 + 4*x\r\n--    sumaPol ejPol1 ejPol2  ==  x^5 + 3*x^4 + 4*x + 3\r\nsumaPol:: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a\r\nsumaPol p q \r\n    | esPolCero p = q\r\n    | esPolCero q = p\r\n    | n1 > n2      = consPol n1 a1 (sumaPol r1 q)\r\n    | n1 < n2      = consPol n2 a2 (sumaPol p r2)\r\n    | otherwise    = consPol n1 (a1+a2) (sumaPol r1 r2)\r\n    where n1 = grado p\r\n          a1 = coefLider p\r\n          r1 = restoPol p\r\n          n2 = grado q\r\n          a2 = coefLider q\r\n          r2 = restoPol q\r\n\r\n-- Propiedad. El polinomio cero es el elemento neutro de la suma.\r\nprop_neutroSumaPol :: Polinomio Int -> Bool\r\nprop_neutroSumaPol p = \r\n    sumaPol polCero p == p\r\n\r\n-- Comprobaci\u00f3n con QuickCheck.\r\n--    ghci> quickCheck prop_neutroSumaPol\r\n--    OK, passed 100 tests.\r\n\r\n-- Propiedad. La suma es conmutativa.\r\nprop_conmutativaSuma :: Polinomio Int -> Polinomio Int -> Bool\r\nprop_conmutativaSuma p q = \r\n    sumaPol p q == sumaPol q p\r\n\r\n-- Comprobaci\u00f3n:\r\n--    ghci> quickCheck prop_conmutativaSuma\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Producto de polinomios                                             --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (multPorTerm t p) es el producto del t\u00e9rmino t por el polinomio\r\n-- p. Por ejemplo,\r\n--    ejTerm                     ==  4*x\r\n--    ejPol2                     ==  x^5 + 5*x^2 + 4*x\r\n--    multPorTerm ejTerm ejPol2  ==  4*x^6 + 20*x^3 + 16*x^2\r\nmultPorTerm :: (Num t, Eq t) => Polinomio t -> Polinomio t -> Polinomio t\r\nmultPorTerm term pol \r\n    | esPolCero pol = polCero\r\n    | otherwise     = consPol (n+m) (a*b) (multPorTerm term r)\r\n    where n = grado term\r\n          a = coefLider term\r\n          m = grado pol\r\n          b = coefLider pol\r\n          r = restoPol pol    \r\n\r\n-- (multPol p q) es el producto de los polinomios p y q. Por\r\n-- ejemplo,\r\n--    ghci> ejPol1\r\n--    3*x^4 + -5*x^2 + 3\r\n--    ghci> ejPol2\r\n--    x^5 + 5*x^2 + 4*x\r\n--    ghci> multPol ejPol1 ejPol2\r\n--    3*x^9 + -5*x^7 + 15*x^6 + 15*x^5 + -25*x^4 + -20*x^3 + 15*x^2 + 12*x\r\nmultPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a\r\nmultPol p q\r\n    | esPolCero p = polCero\r\n    | otherwise    = sumaPol (multPorTerm (termLider p) q)\r\n                             (multPol (restoPol p) q)\r\n\r\n-- Propiedad. El producto de polinomios es conmutativo.\r\nprop_conmutativaProducto :: Polinomio Int -> Polinomio Int -> Bool\r\nprop_conmutativaProducto p q = \r\n    multPol p q == multPol q p\r\n\r\n-- La comprobaci\u00f3n es\r\n--    ghci> quickCheck prop_conmutativaProducto\r\n--    OK, passed 100 tests.\r\n\r\n-- El producto es distributivo respecto de la suma.\r\nprop_distributivaProductoSuma :: Polinomio Int -> Polinomio Int \r\n                                 -> Polinomio Int -> Bool\r\nprop_distributivaProductoSuma p q r =\r\n    multPol p (sumaPol q r) == sumaPol (multPol p q) (multPol p r)\r\n\r\n-- Comprobaci\u00f3n:\r\n--    ghci> quickCheck prop_distributivaProductoSuma\r\n--    OK, passed 100 tests.\r\n\r\n-- polUnidad es el polinomio unidad. Por ejemplo, \r\n--    ghci> polUnidad\r\n--    1\r\npolUnidad:: (Num t, Eq t) => Polinomio t\r\npolUnidad = consPol 0 1 polCero\r\n\r\n-- Propiedad. El polinomio unidad es el elemento neutro del producto.\r\nprop_polUnidad :: Polinomio Int -> Bool\r\nprop_polUnidad p = \r\n    multPol p polUnidad == p\r\n\r\n-- Comprobaci\u00f3n:\r\n--    ghci> quickCheck prop_polUnidad\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Valor de un polinomio en un punto                                  --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (valor p c) es el valor del polinomio p al sustituir su variable por\r\n-- c. Por ejemplo, \r\n--    ejPol1             ==  3*x^4 + -5*x^2 + 3\r\n--    valor ejPol1 0     ==  3\r\n--    valor ejPol1 1     ==  1\r\n--    valor ejPol1 (-2)  ==  31\r\nvalor:: (Num a, Eq a) => Polinomio a -> a -> a\r\nvalor p c \r\n    | esPolCero p = 0\r\n    | otherwise   =  b*c^n + valor r c\r\n    where n = grado p\r\n          b = coefLider p\r\n          r = restoPol p\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Verificaci\u00f3n de raices de polinomios                               --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (esRaiz c p) se verifica si c es una raiz del polinomio p. por\r\n-- ejemplo, \r\n--    ejPol3           ==  6*x^4 + 2*x\r\n--    esRaiz 1 ejPol3  ==  False\r\n--    esRaiz 0 ejPol3  ==  True\r\nesRaiz:: (Num a, Eq a) => a -> Polinomio a -> Bool\r\nesRaiz c p = valor p c == 0\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Derivaci\u00f3n de polinomios                                           --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (derivada p) es la derivada del polinomio p. Por ejemplo, \r\n--    ejPol2           ==  x^5 + 5*x^2 + 4*x\r\n--    derivada ejPol2  ==  5*x^4 + 10*x + 4\r\nderivada :: Polinomio Int -> Polinomio Int\r\nderivada p \r\n    | n == 0     = polCero\r\n    | otherwise  = consPol (n-1) (n*b) (derivada r)\r\n    where n = grado p\r\n          b = coefLider p\r\n          r = restoPol p\r\n\r\n-- Propiedad. La derivada de la suma es la suma de las derivadas.\r\nprop_derivada :: Polinomio Int -> Polinomio Int -> Bool\r\nprop_derivada p q =\r\n    derivada (sumaPol p q) == sumaPol (derivada p) (derivada q)\r\n\r\n-- Comprobaci\u00f3n\r\n--    ghci> quickCheck prop_derivada\r\n--    OK, passed 100 tests. \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Resta de polinomios                                                --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- (resta p q) es la el polinomio obtenido rest\u00e1ndole a p el q. Por\r\n-- ejemplo, \r\n--    ejPol1                  ==  3*x^4 + -5*x^2 + 3\r\n--    ejPol2                  ==  x^5 + 5*x^2 + 4*x\r\n--    restaPol ejPol1 ejPol2  ==  -1*x^5 + 3*x^4 + -10*x^2 + -4*x + 3\r\nrestaPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a\r\nrestaPol p q  = \r\n    sumaPol p (multPorTerm (creaTermino 0 (-1)) q)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1. Definir la funci\u00f3n\r\n--    creaPolDispersa :: (Num a, Eq a) => [a] -> Polinomio a\r\n-- tal que (creaPolDispersa xs) es el polinomio cuya representaci\u00f3n\r\n-- dispersa es xs. Por ejemplo,\r\n--    creaPolDispersa [7,0,0,4,0,3]  ==  7*x^5 + 4*x^2 + 3\r\n-- ---------------------------------------------------------------------\r\n\r\ncreaPolDispersa :: (Num a, Eq a) => [a] -> Polinomio a\r\ncreaPolDispersa []     = polCero\r\ncreaPolDispersa (x:xs) = consPol (length xs) x (creaPolDispersa xs)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 12. Definir la funci\u00f3n\r\n--    multEscalar :: (Num a, Eq a) => a -> Polinomio a -> Polinomio a\r\n-- tal que (multEscalar c p) es el polinomio obtenido multiplicando el\r\n-- n\u00famero c por el polinomio p. Por ejemplo, \r\n--    pol2                    ==  2*x + 3\r\n--    multEscalar 4 pol2      ==  8*x + 12\r\n--    multEscalar (1%4) pol2  ==  1 % 2*x + 3 % 4\r\n-- ---------------------------------------------------------------------\r\n\r\nmultEscalar :: (Num a, Eq a) => a -> Polinomio a -> Polinomio a\r\nmultEscalar c p \r\n  | esPolCero p = polCero\r\n  | otherwise   = consPol n (c*b) (multEscalar c r)\r\n  where n = grado p\r\n        b = coefLider p\r\n        r = restoPol p\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 13. Definir la funci\u00f3n\r\n--    cociente:: (Fractional a, Eq a) => \r\n--               Polinomio a -> Polinomio a -> Polinomio a\r\n-- tal que (cociente p q) es el cociente de la divisi\u00f3n de p entre\r\n-- q. Por ejemplo, \r\n--    pol4  ==  3 % 1*x^4 + 5 % 1*x^2 + 3 % 1\r\n--    pol5  ==  6 % 1*x^2 + 2 % 1*x\r\n--    cociente pol4 pol5  ==  1 % 2*x^2 + (-1) % 6*x + 8 % 9\r\n-- ---------------------------------------------------------------------\r\n\r\ncociente:: (Fractional a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a\r\ncociente p q\r\n    | n2 == 0   = multEscalar (1\/a2) p\r\n    | n1 < n2   = polCero\r\n    | otherwise =  consPol n' a' (cociente p' q)\r\n    where n1 = grado p\r\n          a1 = coefLider p\r\n          n2 = grado q\r\n          a2 = coefLider q\r\n          n' = n1-n2\r\n          a' = a1\/a2\r\n          p' = restaPol p (multPorTerm (creaTermino n' a') q)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 14. Definir la funci\u00f3n\r\n--    resto:: (Fractional a, Eq a) => \r\n--            Polinomio a -> Polinomio a -> Polinomio a\r\n-- tal que (resto p q) es el resto de la divisi\u00f3n de p entre q. Por\r\n-- ejemplo,  \r\n--    pol4  ==  3 % 1*x^4 + 5 % 1*x^2 + 3 % 1\r\n--    pol5  ==  6 % 1*x^2 + 2 % 1*x\r\n--    resto pol4 pol5  ==  (-16) % 9*x + 3 % 1\r\n-- ---------------------------------------------------------------------\r\n\r\nresto :: (Fractional a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a\r\nresto p q = restaPol p (multPol (cociente p q) q)\r\n<\/pre>\n<p>Las soluciones del examen del grupo 4 (impartido por Francisco J. Mart\u00edn) son<\/p>\n<pre lang=\"haskell\">\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1. Se consideran los \u00e1rboles binarios representados\r\n-- mediante el tipo Arbol definido por \r\n--    data Arbol = Hoja Int\r\n--               | Nodo Int  Arbol Arbol\r\n-- Por ejemplo, el \u00e1rbol\r\n--         1\r\n--        \/ \\\r\n--       \/   \\\r\n--      3     2\r\n--     \/ \\   \/ \\\r\n--    5   4 6   7\r\n-- se puede representar por\r\n--    Nodo 1 (Nodo 3 (Hoja 5) (Hoja 4)) (Nodo 2 (Hoja 6) (Hoja 7))\r\n-- En los ejemplos se usar\u00e1n los \u00e1rboles definidos por\r\n--    ej1 = Nodo 1 (Nodo 3 (Hoja 5) (Hoja 4)) (Nodo 2 (Hoja 6) (Hoja 7))\r\n--    ej2 = Nodo 3 (Hoja 1) (Hoja 4)\r\n--    ej3 = Nodo 2 (Hoja 3) (Hoja 5)\r\n--    ej4 = Nodo 1 (Hoja 2) (Nodo 2 (Hoja 3) (Hoja 3))\r\n--    ej5 = Nodo 1 (Nodo 2 (Hoja 3) (Hoja 5)) (Hoja 2)\r\n-- \r\n-- Las capas de un \u00e1rbol binario son las listas de elementos que est\u00e1n a\r\n-- la misma profundidad. Por ejemplo, las capas del \u00e1rbol \r\n--         1\r\n--        \/ \\\r\n--       \/   \\\r\n--      3     2\r\n--     \/ \\   \/ \\\r\n--    5   4 6   7\r\n-- son: [1], [3,2] y [5,4,6,7]\r\n--\r\n-- Definir la funci\u00f3n \r\n--    capas :: Arbol -> [[Int]]\r\n-- tal que (capas a) es la lista de las capas de dicho \u00e1rbol ordenadas\r\n-- seg\u00fan la profunidad. Por ejemplo, \r\n--    capas ej1  ==  [[1],[3,2],[5,4,6,7]]\r\n--    capas ej2  ==  [[3],[1,4]]\r\n--    capas ej3  ==  [[2],[3,5]]\r\n--    capas ej4  ==  [[1],[2,2],[3,3]]\r\n--    capas ej5  ==  [[1],[2,2],[3,5]]\r\n-- ---------------------------------------------------------------------\r\n\r\ndata Arbol = Hoja Int\r\n           | Nodo Int Arbol Arbol\r\n             deriving Show\r\n\r\nej1 = Nodo 1 (Nodo 3 (Hoja 5) (Hoja 4)) (Nodo 2 (Hoja 6) (Hoja 7))\r\nej2 = Nodo 3 (Hoja 1) (Hoja 4)\r\nej3 = Nodo 2 (Hoja 3) (Hoja 5)\r\nej4 = Nodo 1 (Hoja 2) (Nodo 2 (Hoja 3) (Hoja 3))\r\nej5 = Nodo 1 (Nodo 2 (Hoja 3) (Hoja 5)) (Hoja 2)\r\n\r\ncapas :: Arbol -> [[Int]]\r\ncapas (Hoja n) = [[n]]\r\ncapas (Nodo n i d) = [n] : union (capas i) (capas d)\r\n\r\n-- (union xss yss) es la lista obtenida concatenando los\r\n-- correspondientes elementos de xss e yss. Por ejemplo,\r\n--    union [[3,4],[2]] [[5],[7,6,8]]  ==  [[3,4,5],[2,7,6,8]]\r\n--    union [[3,4]]     [[5],[7,6,8]]  ==  [[3,4,5],[7,6,8]]\r\n--    union [[3,4],[2]] [[5]]          ==  [[3,4,5],[2]]\r\nunion :: [[a]] -> [[a]] -> [[a]]\r\nunion [] yss = yss\r\nunion xss [] = xss\r\nunion (xs:xss) (ys:yss) = (xs ++ ys) : union xss yss\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 2. Un \u00e1rbol es sub\u00e1rbol de otro si se puede establecer una\r\n-- correspondencia de los nodos del primero con otros mayores o iguales\r\n-- en el segundo, de forma que se respeten las relaciones de\r\n-- descendencia. Este concepto se resume en varias situaciones posibles: \r\n-- * El primer \u00e1rbol es sub\u00e1rbol del hijo izquierdo del segundo\r\n--   \u00e1rbol. De esta forma ej2 es sub\u00e1rbol de ej1.\r\n-- * El primer \u00e1rbol es sub\u00e1rbol del hijo derecho del segundo \u00e1rbol. De\r\n--   esta forma ej3 es sub\u00e1rbol de ej1.\r\n-- * La ra\u00edz del primer \u00e1rbol es menor o igual que la del segundo, el\r\n--   hijo izquierdo del primer \u00e1rbol es sub\u00e1rbol del hijo izquierdo del\r\n--   segundo y el hijo derecho del primer \u00e1rbol es sub\u00e1rbol del hijo\r\n--   derecho del segundo. De esta forma ej4 es sub\u00e1rbol de ej1.\r\n--\r\n-- Definir la funci\u00f3n \r\n--    subarbol :: Arbol -> Arbol -> Bool\r\n-- tal que (subarbol a1 a2) se verifica si a1 es sub\u00e1rbol de a2. Por\r\n-- ejemplo, \r\n--    subarbol ej2 ej1  ==  True\r\n--    subarbol ej3 ej1  ==  True\r\n--    subarbol ej4 ej1  ==  True\r\n--    subarbol ej5 ej1  ==  False\r\n-- ---------------------------------------------------------------------\r\n\r\nsubarbol :: Arbol -> Arbol -> Bool\r\nsubarbol (Hoja n) (Hoja m) =\r\n    n <= m\r\nsubarbol (Hoja n) (Nodo m i d) =\r\n    n <= m || subarbol (Hoja n) i || subarbol (Hoja n) d\r\nsubarbol (Nodo _ _ _) (Hoja _) =\r\n    False\r\nsubarbol (Nodo n i1 d1) (Nodo m i2 d2) =\r\n    subarbol (Nodo n i1 d1) i2 ||\r\n    subarbol (Nodo n i1 d1) d2 ||\r\n    n <= m &#038;&#038; (subarbol i1 i2) &#038;&#038; (subarbol d1 d2)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.1 (1.2 puntos): Definir la funci\u00f3n \r\n--    intercalaRep :: Eq a => a -> [a] -> [[a]]\r\n-- tal que (intercalaRep x ys), es la lista de las listas obtenidas\r\n-- intercalando x entre los elementos de ys, hasta la primera ocurrencia\r\n-- del elemento x en ys. Por ejemplo,\r\n--    intercalaRep 1 []       ==  [[1]]\r\n--    intercalaRep 1 [1]      ==  [[1,1]]\r\n--    intercalaRep 1 [2]      ==  [[1,2],[2,1]]\r\n--    intercalaRep 1 [1,1]    ==  [[1,1,1]]\r\n--    intercalaRep 1 [1,2]    ==  [[1,1,2]]\r\n--    intercalaRep 1 [2,1]    ==  [[1,2,1],[2,1,1]]\r\n--    intercalaRep 1 [1,2,1]  ==  [[1,1,2,1]]\r\n--    intercalaRep 1 [2,1,1]  ==  [[1,2,1,1],[2,1,1,1]]\r\n--    intercalaRep 1 [1,1,2]  ==  [[1,1,1,2]]\r\n--    intercalaRep 1 [1,2,2]  ==  [[1,1,2,2]]\r\n--    intercalaRep 1 [2,1,2]  ==  [[1,2,1,2],[2,1,1,2]]\r\n--    intercalaRep 1 [2,2,1]  ==  [[1,2,2,1],[2,1,2,1],[2,2,1,1]]\r\n-- ---------------------------------------------------------------------\r\n\r\n-- 1\u00aa definici\u00f3n (con map):\r\nintercalaRep :: Eq a => a -> [a] -> [[a]]\r\nintercalaRep x [] = [[x]]\r\nintercalaRep x (y:ys)\r\n    | x == y    = [x:y:ys]\r\n    | otherwise = (x:y:ys) : (map (y:) (intercalaRep x ys))\r\n\r\n-- 2\u00aa definici\u00f3n (sin map):\r\nintercalaRep2 :: Eq a => a -> [a] -> [[a]]\r\nintercalaRep2 x [] = [[x]]\r\nintercalaRep2 x (y:ys)\r\n    | x == y    = [x:y:ys]\r\n    | otherwise = (x:y:ys) : [y:zs | zs <- intercalaRep2 x ys]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.2.Definir la funci\u00f3n\r\n--    permutacionesRep :: Eq a => [a] -> [[a]]\r\n-- tal que (permutacionesRep xs) es la lista (sin elementos repetidos)\r\n-- de todas las permutaciones con repetici\u00f3n de la lista xs. Por\r\n-- ejemplo, \r\n--    permutacionesRep []         ==  [[]]\r\n--    permutacionesRep [1]        ==  [[1]]\r\n--    permutacionesRep [1,1]      ==  [[1,1]]\r\n--    permutacionesRep [1,2]      ==  [[1,2],[2,1]]\r\n--    permutacionesRep [1,2,1]    ==  [[1,2,1],[2,1,1],[1,1,2]]\r\n--    permutacionesRep [1,1,2]    ==  [[1,1,2],[1,2,1],[2,1,1]]\r\n--    permutacionesRep [2,1,1]    ==  [[2,1,1],[1,2,1],[1,1,2]]\r\n--    permutacionesRep [1,1,1]    ==  [[1,1,1]]\r\n--    permutacionesRep [1,1,2,2]  ==  [[1,1,2,2],[1,2,1,2],[2,1,1,2],\r\n--                                     [1,2,2,1],[2,1,2,1],[2,2,1,1]]\r\n-- ---------------------------------------------------------------------\r\n\r\npermutacionesRep :: Eq a => [a] -> [[a]]\r\npermutacionesRep []     = [[]]\r\npermutacionesRep [x]    = [[x]]\r\npermutacionesRep (x:xs) =\r\n    concat (map (intercalaRep x) (permutacionesRep xs))\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4. Un mont\u00f3n de barriles se construye apilando unos encima\r\n-- de otros por capas, de forma que en cada capa todos los barriles\r\n-- est\u00e1n apoyados sobre dos de la capa inferior y todos los barriles de\r\n-- una misma capa est\u00e1n pegados unos a otros. Por ejemplo, los\r\n-- siguientes montones son v\u00e1lidos:\r\n--             _          _   _                   _\r\n--            \/ \\        \/ \\ \/ \\                 \/ \\\r\n--           _\\_\/_      _\\_\/_\\_\/_   _       _   _\\_\/_   _\r\n--          \/ \\ \/ \\    \/ \\ \/ \\ \/ \\ \/ \\     \/ \\ \/ \\ \/ \\ \/ \\\r\n--          \\_\/ \\_\/    \\_\/ \\_\/ \\_\/ \\_\/     \\_\/ \\_\/ \\_\/ \\_\/\r\n--\r\n-- y los siguientes no son v\u00e1lidos:\r\n--         _   _          _       _               _   _\r\n--        \/ \\ \/ \\        \/ \\     \/ \\             \/ \\ \/ \\\r\n--        \\_\/_\\_\/_      _\\_\/_   _\\_\/_       _   _\\_\/_\\_\/\r\n--          \/ \\ \/ \\    \/ \\ \/ \\ \/ \\ \/ \\     \/ \\ \/ \\ \/ \\\r\n--          \\_\/ \\_\/    \\_\/ \\_\/ \\_\/ \\_\/     \\_\/ \\_\/ \\_\/\r\n--\r\n-- Se puede comprobar que el n\u00famero de formas distintas de construir\r\n-- montones con n barriles en la base M_n viene dado por la siguiente\r\n-- f\u00f3rmula: \r\n--\r\n--              (n-1)\r\n--             -------\r\n--              \\\r\n--               \\\r\n--   M_n = 1 +    )    (n-j) * M_j\r\n--               \/\r\n--              \/\r\n--             -------\r\n--              j = 1\r\n--\r\n-- Definir la funci\u00f3n \r\n--    montones :: Integer -> Integer\r\n-- tal que (montones n) es el n\u00famero de formas distintas de construir\r\n-- montones con n barriles en la base. Por ejemplo,\r\n--    montones 1   ==  1\r\n--    montones 10  ==  4181\r\n--    montones 20  ==  63245986\r\n--    montones 30  ==  956722026041\r\n--\r\n-- Calcular el n\u00famero de formas distintas de construir montones con 50\r\n-- barriles en la base.\r\n-- ---------------------------------------------------------------------\r\n\r\nmontones :: Integer -> Integer\r\nmontones 1 = 1\r\nmontones n = 1 + sum [(n-j)*(montones j) | j <- [1..n-1]]\r\n\r\n-- 2\u00aa definici\u00f3n, a partir de la siguiente observaci\u00f3n\r\n--    M(1) = 1                          = 1\r\n--    M(2) = 1 + M(1)                   = M(1) + M(1)   \r\n--    M(3) = 1 + 2*M(1) + M(2)          = M(2) + (M(1) + M(2))\r\n--    M(4) = 1 + 3*M(1) + 2*M(2) + M(3) = M(3) + (M(1) + M(2) + M(3))\r\nmontones2 :: Int -> Integer\r\nmontones2 n = montonesSuc !! (n-1)\r\n\r\nmontonesSuc :: [Integer]\r\nmontonesSuc = 1 : zipWith (+) montonesSuc (scanl1 (+) montonesSuc)\r\n\r\n-- 3\u00aa definici\u00f3n\r\nmontones3 :: Integer -> Integer\r\nmontones3 0 = 0\r\nmontones3 n = head (montonesAcc [] n)\r\n\r\nmontonesAcc :: [Integer] -> Integer -> [Integer]\r\nmontonesAcc ms 0 = ms\r\nmontonesAcc ms n =\r\n    montonesAcc ((1 + sum (zipWith (*) ms [1..])):ms) (n-1)\r\n\r\n-- El c\u00e1lculo es\r\n--    ghci> montones2 50\r\n--    218922995834555169026\r\n<\/pre>\n<p>Las soluciones del examen del grupo 5 (impartido por Andr\u00e9s Cord\u00f3n y Miguel A. Mart\u00ednez) son<\/p>\n<pre lang=\"haskell\">\r\n-- ---------------------------------------------------------------------\r\n-- \u00a7 Librer\u00edas auxiliares                                             --\r\n-- ---------------------------------------------------------------------\r\n\r\nimport Data.List\r\n\r\n-- ----------------------------------------------------------------------\r\n-- Ejercicio 1.1. Un n\u00famero se dir\u00e1 ordenado si sus cifras est\u00e1n en orden \r\n-- creciente. Por ejemplo, 11257 es ordenado pero 2423 no lo es.\r\n--\r\n-- Definir la lista \r\n--    ordenados :: [Integer]\r\n-- formada  por todos los enteros ordenados. Por ejemplo,\r\n--    ghci> take 20 (dropWhile (<30) ordenados)\r\n--    [33,34,35,36,37,38,39,44,45,46,47,48,49,55,56,57,58,59,66,67]\r\n-- ---------------------------------------------------------------------\r\n\r\nordenados :: [Integer]\r\nordenados = [n | n <- [1..], esOrdenado n]\r\n\r\n-- (esOrdenado x) se verifica si el n\u00famero x es ordenado. Por ejemplo,\r\n--    esOrdenado 359  ==  True\r\n--    esOrdenado 395  ==  False\r\nesOrdenado :: Integer -> Bool\r\nesOrdenado = esOrdenada . show\r\n\r\n-- (esOrdenada xs) se verifica si la lista xs est\u00e1 ordenada. Por\r\n-- ejemplo, \r\n--    esOrdenada [3,5,9]  ==  True\r\n--    esOrdenada [3,9,5]  ==  False\r\n--    esOrdenada \"359\"  ==  True\r\n--    esOrdenada \"395\"  ==  False\r\nesOrdenada :: Ord a => [a] -> Bool\r\nesOrdenada (x:y:xs) = x <= y &#038;&#038; esOrdenada (y:xs)\r\nesOrdenada _        = True\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.2. Calcular en qu\u00e9 posici\u00f3n de la lista aparece el n\u00famero\r\n-- 13333. \r\n-- ---------------------------------------------------------------------\r\n\r\n-- El c\u00e1lculo es\r\n--    ghci> length (takeWhile (<=13333) ordenados)\r\n--    1000\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 2.1. Una lista se dir\u00e1 comprimida si sus elementos\r\n-- consecutivos han sido agrupados. Por ejemplo, la comprimida de\r\n-- \"aaabcccc\" es [(3,'a'),(1,'b'),(4,'c')].\r\n-- \r\n-- Definir la funci\u00f3n    \r\n--    comprimida :: Eq a => [a] -> [(a,Int)] \r\n-- tal que (comprimida xs) es la comprimida de la lista xs. Por ejemplo,\r\n--    comprimida \"aaabcccc\"  ==  [(3,'a'),(1,'b'),(4,'c')]\r\n-- ---------------------------------------------------------------------\r\n\r\n-- 2\u00aa definici\u00f3n (por recursi\u00f3n usando takeWhile):\r\ncomprimida :: Eq a => [a] -> [(Int,a)]\r\ncomprimida [] = []\r\ncomprimida (x:xs) = \r\n    (1 + length (takeWhile (==x) xs),x) : comprimida (dropWhile (==x) xs)\r\n\r\n-- 2\u00aa definici\u00f3n (por recursi\u00f3n sin takeWhile)\r\ncomprimida2 :: Eq a => [a] -> [(Int,a)]\r\ncomprimida2 xs = aux xs 1\r\n    where aux (x:y:zs) n | x == y    = aux (y:zs) (n+1)\r\n                         | otherwise = (n,x) : aux (y:zs) 1\r\n          aux [x]      n             = [(n,x)]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 2.2. Definir la funci\u00f3n\r\n--    expandida :: [(Int,a)] -> [a]\r\n-- tal que (expandida ps) es la lista expandida correspondiente a ps (es\r\n-- decir, es la lista xs tal que la comprimida de xs es ps). Por\r\n-- ejemplo, \r\n--    expandida [(2,1),(3,7),(2,5),(4,7)]  ==  [1,1,7,7,7,5,5,7,7,7,7]\r\n-- ---------------------------------------------------------------------\r\n\r\n-- 1\u00aa definici\u00f3n (por comprensi\u00f3n)\r\nexpandida :: [(Int,a)] -> [a]\r\nexpandida ps = concat [replicate k x | (k,x) <- ps]\r\n\r\n-- 2\u00aa definici\u00f3n (por recursi\u00f3n)\r\nexpandida2 :: [(Int,a)] -> [a]\r\nexpandida2 [] = []\r\nexpandida2 ((n,x):ps) = replicate n x ++ expandida2 ps\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.1. Los \u00e1rboles binarios pueden representarse mediante el\r\n-- tipo de dato \r\n--    data Arbol a = Hoja a | Nodo a (Arbol a) (Arbol a)\r\n-- Un ejemplo de \u00e1rbol es\r\n--    ejArbol = Nodo 7 (Nodo 2 (Hoja 5) (Hoja 4)) (Hoja 9) \r\n-- \r\n-- Un elemento de un \u00e1rbol se dir\u00e1 de nivel k si aparece en el \u00e1rbol a\r\n-- distancia k  de la ra\u00edz. \r\n-- \r\n-- Definir la funci\u00f3n\r\n--    nivel :: Int -> Arbol a -> [a]\r\n-- tal que (nivel k a) es la lista de los elementos de nivel k del \u00e1rbol\r\n-- a. Por ejemplo,\r\n--    nivel 0 ejArbol  ==  [7]\r\n--    nivel 1 ejArbol  ==  [2,9]\r\n--    nivel 2 ejArbol  ==  [5,4]\r\n--    nivel 3 ejArbol  ==  []\r\n-- ---------------------------------------------------------------------\r\n\r\ndata Arbol a = Hoja a | Nodo a (Arbol a) (Arbol a)\r\n\r\nejArbol = Nodo 7 (Nodo 2 (Hoja 5) (Hoja 4)) (Hoja 9) \r\n\r\nnivel :: Int -> Arbol a -> [a]\r\nnivel 0 (Hoja x)     = [x]\r\nnivel 0 (Nodo x _ _) = [x]\r\nnivel k (Hoja _ )    = []\r\nnivel k (Nodo _ i d) = nivel (k-1) i ++ nivel (k-1) d\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.2. Definir la funci\u00f3n\r\n--    todosDistintos :: Eq a => Arbol a -> Bool\r\n-- tal que (todosDistintos a) se verifica si todos los elementos del\r\n-- \u00e1rbol a son distintos entre s\u00ed. Por ejemplo, \r\n--    todosDistintos ejArbol                                       == True\r\n--    todosDistintos (Nodo 7 (Hoja 3) (Nodo 4 (Hoja 7) (Hoja 2)))  ==  False\r\n-- ---------------------------------------------------------------------\r\n\r\ntodosDistintos :: Eq a => Arbol a -> Bool\r\ntodosDistintos a = xs == nub xs\r\n    where xs = preorden a\r\n\r\npreorden :: Arbol a -> [a]\r\npreorden (Hoja x)     = [x]\r\npreorden (Nodo x i d) = x : (preorden i ++ preorden d)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4.1. En un colisionador de part\u00edculas se disponen m placas,\r\n-- con n celdillas cada una. Cada celdilla detecta si alguna part\u00edcula \r\n-- ha pasado por ella (1 si ha detectado una part\u00edcula, 0 en caso\r\n-- contrario). El siguiente ejemplo muestra 5 placas con 9 celdillas\r\n-- cada una: \r\n--    experimento:: [[Int]]\r\n--    experimento = [[0, 0, 1, 1, 0, 1, 0, 0, 1],\r\n--                   [0, 1, 0, 1, 0, 1, 0, 1, 0],\r\n--                   [1, 0, 1, 0, 0, 0, 1, 0, 0],\r\n--                   [0, 1, 0, 0, 0, 1, 0, 1, 0],\r\n--                   [1, 0, 0, 0, 1, 0, 0, 0, 1]]\r\n-- Se quiere reconstruir las trayectorias que han realizado las\r\n-- part\u00edculas que  atraviesan dichas placas.\r\n-- \r\n-- Una trayectoria de una part\u00edcula vendr\u00e1 dada por un par, donde la\r\n-- primera componente indica la celdilla por la que pas\u00f3 en la primera\r\n-- placa y la segunda componente ser\u00e1 una lista que indica el camino\r\n-- seguido en las sucesivas placas. Es decir, cada elemento de la lista\r\n-- indicar\u00e1 si de una placa a la siguiente, la part\u00edcula se desvi\u00f3 una\r\n-- celdilla hacia la derecha (+1), hacia la izquierda (-1) o pas\u00f3 por la\r\n-- misma celdilla (0). Por ejemplo, una trayectoria en el ejemplo\r\n-- anterior ser\u00eda: \r\n--        [(2,[-1,1,-1,-1])]\r\n-- Se puede observar que es posible crear m\u00e1s de una trayectoria para la \r\n-- misma  part\u00edcula. \r\n-- \r\n-- Definir la funci\u00f3n\r\n--    calculaTrayectorias :: [[Int]] -> [(Int,[Int])] \r\n-- que devuelva una lista con todas las trayectorias posibles para un\r\n-- experimento. Por ejemplo,\r\n--    ghci> calculaTrayectorias experimento  \r\n--    [(2,[-1,-1,1,-1]),  (2,[-1,1,-1,-1]), (2,[1,-1,-1,-1]), \r\n--     (3,[0,-1,-1,-1]), \r\n--     (5,[0,1,-1,-1]),   (5,[0,1,1,1]),\r\n--     (8,[-1,-1,-1,-1]), (8,[-1,-1,1,1])]\r\n-- ---------------------------------------------------------------------\r\n\r\nexperimento:: [[Int]]\r\nexperimento = [[0, 0, 1, 1, 0, 1, 0, 0, 1],\r\n               [0, 1, 0, 1, 0, 1, 0, 1, 0],\r\n               [1, 0, 1, 0, 0, 0, 1, 0, 0],\r\n               [0, 1, 0, 0, 0, 1, 0, 1, 0],\r\n               [1, 0, 0, 0, 1, 0, 0, 0, 1]]\r\n\r\ncalculaTrayectorias :: [[Int]] -> [(Int,[Int])]\r\ncalculaTrayectorias [] = []\r\ncalculaTrayectorias (xs:xss) = \r\n    [(i,ys) | (i,e) <- zip [0..] xs, e==1, ys <- posiblesTrayectorias i xss]\r\n\r\n-- 1\u00aa definici\u00f3n (por recursi\u00f3n)\r\nposiblesTrayectorias :: Int -> [[Int]] -> [[Int]]\r\nposiblesTrayectorias i [] = [[]]\r\nposiblesTrayectorias i (xs:xss) = \r\n    [desp:ys | desp <- [-1,0,1], \r\n               i+desp >= 0 && i+desp < length xs, \r\n               xs!!(i+desp) == 1,\r\n               ys <- posiblesTrayectorias (i+desp) xss]\r\n\r\n-- 2\u00aa definici\u00f3n (por recursi\u00f3n con acumulador)\r\nposiblesTrayectorias' i xss = posiblesTrayectoriasRecAcum i [[]] xss\r\n\r\nposiblesTrayectoriasRecAcum i yss [] = yss\r\nposiblesTrayectoriasRecAcum i yss (xs:xss) = \r\n  concat[posiblesTrayectoriasRecAcum idx [ys++[idx-i] | ys <- yss] xss\r\n        | idx <- [i-1..i+1], idx >= 0 && idx < length xs, xs!!idx == 1]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4.2. Consideraremos una trayectoria v\u00e1lida si no cambia de\r\n-- direcci\u00f3n. Esto es, si una part\u00edcula tiene una trayectoria hacia la\r\n-- izquierda, no podr\u00e1 desviarse a la derecha posteriormenete y vice versa. \r\n-- \r\n-- Definir la funci\u00f3n\r\n--    trayectoriasValidas :: [(Int,[Int])] -> [(Int,[Int])]\r\n-- tal que (trayectoriasValidas xs) es la lista de las trayectorias de\r\n-- xs que son v\u00e1lidas. Por ejemplo,\r\n--    ghci> trayectoriasValidas (calculaTrayectorias experimento) \r\n--    [(3,[0,-1,-1,-1]),(5,[0,1,1,1]),(8,[-1,-1,-1,-1])]\r\n-- ---------------------------------------------------------------------\r\n\r\ntrayectoriasValidas :: [(Int,[Int])] -> [(Int,[Int])]\r\ntrayectoriasValidas xss = [(i,xs) | (i,xs) <- xss, trayectoriaValida xs]\r\n\r\ntrayectoriaValida :: [Int] -> Bool\r\ntrayectoriaValida xs = not (1 `elem` xs && (-1) `elem` xs) \r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>En la clase de hoy del curso Inform\u00e1tica (de 1\u00ba de Grado en Matem\u00e1ticas) se ha realizado el 4\u00ba examen del curso. Adem\u00e1s, durante esta semana se han realizado los ex\u00e1menes de los otros grupos. A continuaci\u00f3n se muestran las soluciones de dichos ex\u00e1menes. Las soluciones del examen del grupo 3 son<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","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":[222],"tags":[270,300],"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\/4198"}],"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=4198"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4198\/revisions"}],"predecessor-version":[{"id":4199,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4198\/revisions\/4199"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=4198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=4198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=4198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}