{"id":4349,"date":"2014-06-18T18:44:47","date_gmt":"2014-06-18T16:44:47","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=4349"},"modified":"2014-06-22T08:46:13","modified_gmt":"2014-06-22T06:46:13","slug":"i1m2013-6o-examen-de-programacion-con-haskell","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/i1m2013-6o-examen-de-programacion-con-haskell\/","title":{"rendered":"I1M2013: 6\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<\/a> (de 1\u00ba de Grado en Matem\u00e1ticas) se ha realizado el 6\u00ba examen del curso en dos turnos. A continuaci\u00f3n se muestran los ejercicios y soluciones de cada examen.<\/p>\n<h3>Ejercicios y soluciones del primer turno<\/h3>\n<p><!--more--><\/p>\n<pre lang=\"haskell\">\n-- Librer\u00edas auxiliares                                             --\n-- ====================\nimport Data.List\nimport Data.Array\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 1 [2 puntos]. Definir la funci\u00f3n \n--     siembra :: [a] -> [[a]] -> [[a]]\n-- tal que (siembra xs yss) es la lista obtenida introduciendo cada uno\n-- de los elementos de xs en la lista correspondiente de yss; es decir,\n-- el primer elemento de xs en la primera lista de yss, el segundo\n-- elemento de xs en la segunda lista de yss, etc. Por ejemplo,\n--    siembra [1,2,3] [[4,7],[6],[9,5,8]]  ==  [[1,4,7],[2,6],[3,9,5,8]]\n--    siembra [1,2] [[4,7],[6],[9,5,8]]    ==  [[1,4,7],[2,6],[9,5,8]]\n--    siembra [1,2,3] [[4,7],[6]]          ==  [[1,4,7],[2,6]]\n-- ---------------------------------------------------------------------\n\nsiembra :: [a] -> [[a]] -> [[a]]\nsiembra [] yss          = yss\nsiembra xs []           = []\nsiembra (x:xs) (ys:yss) = (x:ys) : siembra xs yss\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2 [2 puntos]. Definir la funci\u00f3n \n--    primosEquidistantes :: Integer -> [(Integer,Integer)]\n-- tal que (primosEquidistantes k) es la lista de los pares de primos\n-- consecutivos cuya diferencia es k. Por ejemplo,\n--    take 3 (primosEquidistantes 2)  ==  [(3,5),(5,7),(11,13)]\n--    take 3 (primosEquidistantes 4)  ==  [(7,11),(13,17),(19,23)]\n--    take 3 (primosEquidistantes 6)  ==  [(23,29),(31,37),(47,53)]\n--    take 3 (primosEquidistantes 8)  ==  [(89,97),(359,367),(389,397)]\n-- ---------------------------------------------------------------------\n\nprimosEquidistantes :: Integer -> [(Integer,Integer)]\nprimosEquidistantes k = aux primos\n    where aux (x:y:ps) | y - x == k = (x,y) : aux (y:ps)\n                       | otherwise  = aux (y:ps)\n \n-- (primo x) se verifica si x es primo. Por ejemplo,\n--    primo 7  ==  True\n--    primo 8  ==  False\nprimo :: Integer -> Bool\nprimo x = [y | y <- [1..x], x `rem` y == 0] == [1,x]\n \n-- primos es la lista de los n\u00fameros primos. Por ejemplo,\n--    take 10 primos  ==  [2,3,5,7,11,13,17,19,23,29]\nprimos :: [Integer]\nprimos = 2 : [x | x <- [3,5..], primo x]\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 3 [2 puntos]. Se consideran los \u00e1rboles con operaciones\n-- booleanas definidos por  \n--    data ArbolB = H Bool \n--                | Conj ArbolB ArbolB\n--                | Disy ArbolB ArbolB\n--                | Neg ArbolB\n-- \n-- Por ejemplo, los \u00e1rboles\n--                Conj                            Conj          \n--               \/   \\                           \/   \\          \n--              \/     \\                         \/     \\         \n--           Disy      Conj                  Disy      Conj     \n--          \/   \\       \/  \\                \/   \\      \/   \\    \n--       Conj    Neg   Neg True          Conj    Neg   Neg  True \n--       \/  \\    |     |                 \/  \\    |     |        \n--    True False False False          True False True  False     \n--\n-- se definen por\n--    ej1, ej2:: ArbolB\n--    ej1 = Conj (Disy (Conj (H True) (H False))\n--                     (Neg (H False)))\n--               (Conj (Neg (H False))\n--                     (H True))\n--    \n--    ej2 = Conj (Disy (Conj (H True) (H False))\n--                     (Neg (H True)))\n--               (Conj (Neg (H False))\n--                     (H True))\n-- \n-- Definir la funci\u00f3n \n--    valor:: ArbolB -> Bool\n-- tal que (valor ar) es el resultado de procesar el \u00e1rbol realizando\n-- las operaciones booleanas especificadas en los nodos. Por ejemplo,\n--    valor ej1 == True\n--    valor ej2 == False\n-- ---------------------------------------------------------------------\n\ndata ArbolB = H Bool \n            | Conj ArbolB ArbolB\n            | Disy ArbolB ArbolB\n            | Neg ArbolB\n\nej1, ej2:: ArbolB\nej1 = Conj (Disy (Conj (H True) (H False))\n                 (Neg (H False)))\n           (Conj (Neg (H False))\n                 (H True))\n\nej2 = Conj (Disy (Conj (H True) (H False))\n                 (Neg (H True)))\n           (Conj (Neg (H False))\n                 (H True))\n\nvalor:: ArbolB -> Bool\nvalor (H x)     = x\nvalor (Neg a)    = not (valor a)\nvalor (Conj i d) = (valor i) && (valor d)\nvalor (Disy i d) = (valor i) || (valor d)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 4 [2 puntos]. La matriz de Vandermonde generada por\n-- [a(1),a(2),a(3),...,a(n)] es la siguiente\n--    |1  a(1)  a(1)^2 ... a(1)^{n-1}|\n--    |1  a(2)  a(2)^2 ... a(2)^{n-1}|\n--    |1  a(3)  a(3)^2 ... a(3)^{n-1}|\n--    |.  .     .          .         |\n--    |.  .     .          .         |\n--    |.  .     .          .         |\n--    |1  a(n)  a(n)^2 ... a(n)^{n-1}|\n--\n-- Las matrices se representan con tablas cuyos \u00edndices son pares de\n-- n\u00fameros naturales.  \n--    type Matriz a = Array (Int,Int) a\n--\n-- Definir la funci\u00f3n \n--    vandermonde:: [Integer] -> Matriz Integer\n-- tal que (vandermonde xs) es la matriz de Vandermonde cuyos\n-- generadores son los elementos de xs. Por ejemplo,\n--    ghci> vandermonde [5,2,3,4]\n--    array ((1,1),(4,4)) [((1,1),1),((1,2),5),((1,3),25),((1,4),125),\n--                         ((2,1),1),((2,2),2),((2,3), 4),((2,4),  8),\n--                         ((3,1),1),((3,2),3),((3,3), 9),((3,4), 27),\n--                         ((4,1),1),((4,2),4),((4,3),16),((4,4), 64)]\n-- ---------------------------------------------------------------------\n\ntype Matriz a = Array (Int,Int) a\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nvandermonde1 :: [Integer] -> Matriz Integer\nvandermonde1 xs = array ((1,1), (n,n)) \n                  [((i,j), f i j) | i <- [1..n], j <- [1..n]]\n      where n     = length xs\n            f i j = (xs!!(i-1))^(j-1)\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nvandermonde2 :: [Integer] -> Matriz Integer\nvandermonde2 xs = listArray ((1,1),(n,n)) (concat (listaVandermonde xs))\n    where n = length xs\n\n-- (listaVandermonde xs) es la lista correspondiente a la matriz de\n-- Vandermonde generada por xs. Por ejemplo,\n--    ghci> listaVandermonde [5,2,3,4]\n--    [[1,5,25,125],[1,2,4,8],[1,3,9,27],[1,4,16,64]]\nlistaVandermonde :: [Integer] -> [[Integer]]\nlistaVandermonde xs = [[x^i | i <- [0..n-1]] | x <- xs]\n    where n = length xs\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 5 [2 puntos]. El n\u00famero 595 es pal\u00edndromo y, adem\u00e1s, es\n-- suma de cuadrados consecutivos, pues \n--    595 = 6^2 + 7^2 + 8^2 + 9^2 + 10^2 + 11^2 + 12^2. \n-- \n-- Definir la funci\u00f3n \n--    sucesion:: [Integer]\n-- tal que sucesion es la lista de los n\u00fameros que son pal\u00edndromos y\n-- suma de cuadrados consecutivos. Por ejemplo,\n--    take 10 sucesion == [1,4,5,9,55,77,121,181,313,434]\n--    take 15 sucesion == [1,4,5,9,55,77,121,181,313,434,484,505,545,595,636]\n-- ---------------------------------------------------------------------\n\nsucesion:: [Integer]\nsucesion = [x | x <-[1..], palindromo x, esSumaCuadradosConsecutivos x]\n\npalindromo :: Integer -> Bool\npalindromo n = show n == reverse (show n)\n\nsucSumaCuadradosDesde :: Integer -> [Integer]    \nsucSumaCuadradosDesde k = scanl (\\s n -> s + n^2) 0 [k..]\n\n\nesSumaCuadradosConsecutivos n =\n    or [pertenece n (sucSumaCuadradosDesde k) | k <- [1..m]]\n    where pertenece x xs = elem x (takeWhile (<=x) xs)\n          m              = floor (sqrt (fromIntegral n))\n\n-- 2\u00aa soluci\u00f3n para esSumaCuadradosConsecutivos:\n        \nesSumaCuadradosConsecutivos2 n = any (==n) (map sum yss)\n    where m = floor (sqrt (fromIntegral n))\n          xss = segmentos [1..m]\n          yss = map (map (^2)) xss\n\nsegmentos :: [a] -> [[a]]\nsegmentos xs = concat [tail (inits ys) | ys <- init (tails xs)]\n  \nsucesion2:: [Integer]\nsucesion2 = [x | x <-[1..], palindromo x, esSumaCuadradosConsecutivos2 x]\n<\/pre>\n<h3>Ejercicios y soluciones del segundo turno<\/h3>\n<pre lang=\"haskell\">\n-- Librer\u00eda auxiliar\n-- =================\nimport Data.Array\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 1 [2 puntos]. Definir la funci\u00f3n\n--    divisiblesPorPrimero :: [Int] -> Bool\n-- tal que (divisibles xs) se verifica si todos los elementos positivos\n-- de xs son divisibles por el primero. Por ejemplo,\n--    divisiblesPorPrimero [2,6,-3,0,18,-17,10]  ==  True\n--    divisiblesPorPrimero [-13]                 ==  True\n--    divisiblesPorPrimero [-3,6,1,-3,9,18]      ==  False\n--    divisiblesPorPrimero [5,-2,-6,3]           ==  False\n--    divisiblesPorPrimero []                    ==  False\n--    divisiblesPorPrimero [0,2,4]               ==  False\n-- ---------------------------------------------------------------------\n\n-- 1\u00aa definici\u00f3n (por comprensi\u00f3n)\ndivisiblesPorPrimero1 :: [Int] -> Bool\ndivisiblesPorPrimero1 []     = False\ndivisiblesPorPrimero1 (0:_)  = False\ndivisiblesPorPrimero1 (x:xs) = and [y `rem` x == 0 | y <- xs, y > 0]\n\n-- 2\u00aa definici\u00f3n (por recursi\u00f3n)\ndivisiblesPorPrimero2 :: [Int] -> Bool\ndivisiblesPorPrimero2 []     = False\ndivisiblesPorPrimero2 (0:_)  = False\ndivisiblesPorPrimero2 (x:xs) = aux xs\n    where aux [] = True\n          aux (y:ys) | y > 0     = y `rem` x == 0 && aux ys\n                     | otherwise = aux ys \n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2 [2 puntos]. Definir la constante\n--    primosConsecutivosConMediaCapicua :: [(Int,Int,Int)]\n-- tal que primosConsecutivosConMediaCapicua es la lista de las ternas \n-- (x,y,z) tales que x e y son primos consecutivos tales que su media,\n-- z, es capic\u00faa. Por ejemplo,\n--    ghci> take 5 primosConsecutivosConMediaCapicua\n--    [(3,5,4),(5,7,6),(7,11,9),(97,101,99),(109,113,111)]\n-- Calcular cu\u00e1ntos hay anteriores a 2014.\n-- ---------------------------------------------------------------------\n\nprimosConsecutivosConMediaCapicua :: [(Int,Int,Int)]\nprimosConsecutivosConMediaCapicua =\n    [(x,y,z) | (x,y) <- zip primos (tail primos),\n               let z = (x + y) `div` 2,\n               capicua z]\n\n-- (primo x) se verifica si x es primo. Por ejemplo,\n--    primo 7  ==  True\n--    primo 8  ==  False\nprimo :: Int -> Bool\nprimo x = [y | y <- [1..x], x `rem` y == 0] == [1,x]\n\n-- primos es la lista de los n\u00fameros primos mayores que 2. Por ejemplo,\n--    take 10 primos  ==  [3,5,7,11,13,17,19,23,29]\nprimos :: [Int]\nprimos = [x | x <- [3,5..], primo x]\n\n-- (capicua x) se verifica si x es capic\u00faa. Por ejemplo,\ncapicua :: Int -> Bool\ncapicua x = ys == reverse ys\n    where ys = show x\n\n-- El c\u00e1lculo es\n--    ghci> length (takeWhile (\\(x,y,z) -> y < 2014) primosConsecutivosConMediaCapicua)\n--    20\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 3 [2 puntos]. Un elemento x de un conjunto xs es minimal\n-- respecto de una relaci\u00f3n r si no existe ning\u00fan elemento y en xs tal\n-- que (r y x). Por ejemplo,  \n-- \n-- Definir la funci\u00f3n\n--    minimales :: Eq a => (a -> a -> Bool) -> [a] -> [a]\n-- tal que (minimales xss) es la lista de los elementos minimales de\n-- xs. Por ejemplo, \n--    ghci> minimales (\\x y -> y `rem` x == 0) [2,3,6,12,18]\n--    [2,3]\n--    ghci> minimales (\\x y -> x `rem` y == 0) [2,3,6,12,18]\n--    [12,18]\n--    ghci> minimales (\\x y -> maximum x < maximum y) [\"ac\",\"cd\",\"aacb\"]\n--    [\"ac\",\"aacb\"]\n--    ghci> minimales (\\xs ys -> all (`elem` ys) xs) [\"ab\",\"c\",\"abc\",\"d\",\"dc\"]\n--    [\"ab\",\"c\",\"d\"]\n-- ---------------------------------------------------------------------\n\nminimales :: Eq a => (a -> a -> Bool) -> [a] -> [a]\nminimales r xs = [x | x <- xs, esMinimal r xs x]\n\n-- (esMinimal r xs x) s verifica si xs no tiene ning\u00fan elemento menor\n-- que x respecto de la relaci\u00f3n r. \nesMinimal :: Eq a => (a -> a -> Bool) -> [a] -> a -> Bool\nesMinimal r xs x = null [y | y <- xs, y \/= x, r y x]\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 4 [2 puntos]. Una matriz es monomial si en cada una de sus\n-- filas y columnas todos los elementos son nulos excepto 1. Por\n-- ejemplo, de las matrices \n--    |0  0 3 0|     |0  0 3 0|\n--    |0 -2 0 0|     |0 -2 0 0|\n--    |1  0 0 0|     |1  0 0 0|\n--    |0  0 0 1|     |0  1 0 1|\n-- la primera es monomial y la segunda no lo es.\n--\n-- Las matrices puede representarse mediante tablas cuyos\n-- \u00edndices son pares de n\u00fameros naturales:    \n--    type Matriz = Array (Int,Int) Int\n-- Por ejemplo, las matrices anteriores se pueden definir por\n--    ej1, ej2 :: Matriz\n--    ej1 = listArray ((1,1),(4,4)) [0,  0, 3, 0,\n--                                   0, -2, 0, 0,\n--                                   1,  0, 0, 0,\n--                                   0,  0, 0, 1]\n--    ej2 = listArray ((1,1),(4,4)) [0,  0, 3, 0,\n--                                   0, -2, 0, 0,\n--                                   1,  0, 0, 0,\n--                                   0,  1, 0, 1]\n-- Definir la funci\u00f3n \n--    esMonomial :: Matriz -> Bool\n-- tal que (esMonomial p) se verifica si la matriz p es monomial. Por\n-- ejemplo, \n--    esMonomial ej1  ==  True\n--    esMonomial ej2  ==  False\n-- ---------------------------------------------------------------------\n\ntype Matriz = Array (Int,Int) Int\n\nej1, ej2 :: Matriz\nej1 = listArray ((1,1),(4,4)) [0,  0, 3, 0,\n                               0, -2, 0, 0,\n                               1,  0, 0, 0,\n                               0,  0, 0, 1]\nej2 = listArray ((1,1),(4,4)) [0,  0, 3, 0,\n                               0, -2, 0, 0,\n                               1,  0, 0, 0,\n                               0,  1, 0, 1]\n\nesMonomial :: Matriz -> Bool\nesMonomial p = all esListaMonomial (filas p ++ columnas p)\n\n-- (filas p) es la lista de las filas de la matriz p. Por ejemplo,\n--    filas ej1  ==  [[0,0,3,0],[0,-2,0,0],[1,0,0,0],[0,0,0,1]]\nfilas :: Matriz -> [[Int]]\nfilas p = [[p!(i,j) | j <- [1..n]] | i <- [1..m]]\n    where (_,(m,n)) = bounds p\n\n-- (columnas p) es la lista de las columnas de la matriz p. Por ejemplo,\n--    columnas ej1  ==  [[0,0,1,0],[0,-2,0,0],[3,0,0,0],[0,0,0,1]]\ncolumnas :: Matriz -> [[Int]]\ncolumnas p = [[p!(i,j) | i <- [1..m]] | j <- [1..n]]\n    where (_,(m,n)) = bounds p\n\n-- (esListaMonomial xs) se verifica si todos los elementos de xs excepto\n-- uno son nulos. Por ejemplo,\n--    esListaMonomial [0,3,0,0]  ==  True\n--    esListaMonomial [0,3,0,2]  ==  False\n--    esListaMonomial [0,0,0,0]  ==  False\nesListaMonomial :: [Int] -> Bool\nesListaMonomial xs = length (filter (\/=0) xs) == 1\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 5 [2 puntos]. Se consideran las expresiones vectoriales\n-- formadas por un vector, la suma de dos expresiones vectoriales o el\n-- producto de un entero por una expresi\u00f3n vectorial. El siguiente tipo\n-- de dato define las expresiones vectoriales \n--    data ExpV = Vec Int Int\n--              | Sum ExpV ExpV\n--              | Mul Int ExpV\n--              deriving Show\n-- Definir la funci\u00f3n \n--    valor :: ExpV -> (Int,Int)\n-- tal que (valor e) es el valor de la expresi\u00f3n vectorial c. Por\n-- ejemplo, \n--    valor (Vec 1 2)                                  ==  (1,2)\n--    valor (Sum (Vec 1 2 ) (Vec 3 4))                 ==  (4,6)\n--    valor (Mul 2 (Vec 3 4))                          ==  (6,8)\n--    valor (Mul 2 (Sum (Vec 1 2 ) (Vec 3 4)))         ==  (8,12)\n--    valor (Sum (Mul 2 (Vec 1 2)) (Mul 2 (Vec 3 4)))  ==  (8,12)\n-- ---------------------------------------------------------------------\n\ndata ExpV = Vec Int Int\n          | Sum ExpV ExpV\n          | Mul Int ExpV\n          deriving Show\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\nvalor :: ExpV -> (Int,Int)\nvalor (Vec x y)   = (x,y)\nvalor (Sum e1 e2) = (x1+x2,y1+y2) where (x1,y1) = valor e1  \n                                        (x2,y2) = valor e2  \nvalor (Mul n e)   = (n*x,n*y) where (x,y) = valor e  \n\n-- 2\u00aa soluci\u00f3n\n-- ===========\nvalor2 :: ExpV -> (Int,Int)\nvalor2 (Vec a b)   = (a, b)\nvalor2 (Sum e1 e2) = suma (valor2 e1) (valor2 e2)\nvalor2 (Mul n e1)  = multiplica n (valor2 e1)\n\nsuma :: (Int,Int) -> (Int,Int) -> (Int,Int)\nsuma (a,b) (c,d) = (a+c,b+d)\n\nmultiplica :: Int -> (Int, Int) -> (Int, Int)\nmultiplica n (a,b) = (n*a,n*b)\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 6\u00ba examen del curso en dos turnos. A continuaci\u00f3n se muestran los ejercicios y soluciones de cada examen. Ejercicios y soluciones del primer turno<\/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\/4349"}],"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=4349"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4349\/revisions"}],"predecessor-version":[{"id":4350,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4349\/revisions\/4350"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=4349"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=4349"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=4349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}