{"id":8551,"date":"2024-05-14T06:00:37","date_gmt":"2024-05-14T04:00:37","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=8551"},"modified":"2024-05-13T19:23:24","modified_gmt":"2024-05-13T17:23:24","slug":"14-may-24","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/14-may-24\/","title":{"rendered":"Matrices de Toepliz"},"content":{"rendered":"<p>Una <a href=\"https:\/\/bit.ly\/3pqjY9D\">matriz de Toeplitz<\/a> es una matriz cuadrada que es constante a lo largo de las diagonales paralelas a la diagonal principal. Por ejemplo,<\/p>\n<pre lang=\"haskell\">\n   |2 5 1 6|       |2 5 1 6|\n   |4 2 5 1|       |4 2 6 1|\n   |7 4 2 5|       |7 4 2 5|\n   |9 7 4 2|       |9 7 4 2|\n<\/pre>\n<p>la primera es una matriz de Toeplitz y la segunda no lo es.<\/p>\n<p>Las anteriores matrices se pueden definir por<\/p>\n<pre lang=\"haskell\">\n   ej1, ej2 :: Array (Int,Int) Int\n   ej1 = listArray ((1,1),(4,4)) [2,5,1,6,4,2,5,1,7,4,2,5,9,7,4,2]\n   ej2 = listArray ((1,1),(4,4)) [2,5,1,6,4,2,6,1,7,4,2,5,9,7,4,2]\n<\/pre>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"haskell\">\n   esToeplitz :: Eq a => Array (Int,Int) a -> Bool\n<\/pre>\n<p>tal que <code>esToeplitz p<\/code> se verifica si la matriz <code>p<\/code> es de Toeplitz. Por ejemplo,<\/p>\n<pre lang=\"haskell\">\n   esToeplitz ej1  ==  True\n   esToeplitz ej2  ==  False\n<\/pre>\n<p><!--more--><\/p>\n<h2>1. Soluciones en Haskell<\/h2>\n<pre lang=\"haskell\">\nimport Data.Array (Array, (!), bounds, listArray)\nimport Test.Hspec (Spec, describe, hspec, it, shouldBe)\n\nej1, ej2 :: Array (Int,Int) Int\nej1 = listArray ((1,1),(4,4)) [2,5,1,6,4,2,5,1,7,4,2,5,9,7,4,2]\nej2 = listArray ((1,1),(4,4)) [2,5,1,6,4,2,6,1,7,4,2,5,9,7,4,2]\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nesToeplitz1 :: Eq a => Array (Int,Int) a -> Bool\nesToeplitz1 p =\n  esCuadrada p &&\n  all todosIguales (diagonalesPrincipales p)\n\n-- (esCuadrada p) se verifica si la matriz p es cuadrada. Por ejemplo,\n--    esCuadrada (listArray ((1,1),(4,4)) [1..])  ==  True\n--    esCuadrada (listArray ((1,1),(3,4)) [1..])  ==  False\nesCuadrada :: Eq a => Array (Int,Int) a -> Bool\nesCuadrada p = m == n\n  where (_,(m,n)) = bounds p\n\n-- (diagonalesPrincipales p) es la lista de las diagonales principales\n-- de p. Por ejemplo,\n--    \u03bb> diagonalesPrincipales ej1\n--    [[2,2,2,2],[5,5,5],[1,1],[6],[2,2,2,2],[4,4,4],[7,7],[9]]\n--    \u03bb> diagonalesPrincipales ej2\n--    [[2,2,2,2],[5,6,5],[1,1],[6],[2,2,2,2],[4,4,4],[7,7],[9]]\ndiagonalesPrincipales :: Array (Int,Int) a -> [[a]]\ndiagonalesPrincipales p =\n  [[p ! i |i <- is] | is <- posicionesDiagonalesPrincipales m n]\n  where (_,(m,n)) = bounds p\n\n-- (posicionesDiagonalesPrincipales m n) es la lista de las\n-- posiciones de las diagonales principales de una matriz con m filas y\n-- n columnas. Por ejemplo,\n--   \u03bb> mapM_ print (posicionesDiagonalesPrincipales 3 4)\n--   [(3,1)]\n--   [(2,1),(3,2)]\n--   [(1,1),(2,2),(3,3)]\n--   [(1,2),(2,3),(3,4)]\n--   [(1,3),(2,4)]\n--   [(1,4)]\n--   \u03bb> mapM_ print (posicionesDiagonalesPrincipales 4 4)\n--   [(4,1)]\n--   [(3,1),(4,2)]\n--   [(2,1),(3,2),(4,3)]\n--   [(1,1),(2,2),(3,3),(4,4)]\n--   [(1,2),(2,3),(3,4)]\n--   [(1,3),(2,4)]\n--   [(1,4)]\n--   \u03bb> mapM_ print (posicionesDiagonalesPrincipales 4 3)\n--   [(4,1)]\n--   [(3,1),(4,2)]\n--   [(2,1),(3,2),(4,3)]\n--   [(1,1),(2,2),(3,3)]\n--   [(1,2),(2,3)]\n--   [(1,3)]\nposicionesDiagonalesPrincipales :: Int -> Int -> [[(Int, Int)]]\nposicionesDiagonalesPrincipales m n =\n  [zip [i..m] [1..n] | i <- [m,m-1..1]] ++\n  [zip [1..m] [j..n] | j <- [2..n]]\n\n-- (todosIguales xs) se verifica si todos los elementos de xs son\n-- iguales. Por ejemplo,\n--    todosIguales [5,5,5]  ==  True\n--    todosIguales [5,4,5]  ==  False\ntodosIguales :: Eq a => [a] -> Bool\ntodosIguales []     = True\ntodosIguales (x:xs) = all (== x) xs\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nesToeplitz2 :: Eq a => Array (Int,Int) a -> Bool\nesToeplitz2 p = m == n &&\n                and [p!(i,j) == p!(i+1,j+1) |\n                     i <- [1..n-1], j <- [1..n-1]]\n  where (_,(m,n)) = bounds p\n\n-- Verificaci\u00f3n\n-- ============\n\nverifica :: IO ()\nverifica = hspec spec\n\nspecG :: (Array (Int,Int) Int -> Bool) -> Spec\nspecG esToeplitz = do\n  it \"e1\" $\n    esToeplitz ej1 `shouldBe` True\n  it \"e2\" $\n    esToeplitz ej2 `shouldBe` False\n\nspec :: Spec\nspec = do\n  describe \"def. 1\" $ specG esToeplitz1\n  describe \"def. 2\" $ specG esToeplitz2\n\n-- La verificaci\u00f3n es\n--    \u03bb> verifica\n--    4 examples, 0 failures\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> esToeplitz1 (listArray ((1,1),(2*10^3,2*10^3)) (repeat 1))\n--    True\n--    (2.26 secs, 2,211,553,888 bytes)\n--    \u03bb> esToeplitz2 (listArray ((1,1),(2*10^3,2*10^3)) (repeat 1))\n--    True\n--    (4.26 secs, 3,421,651,032 bytes)\n<\/pre>\n<h2>2. Soluciones en Python<\/h2>\n<pre lang=\"python\">\nfrom timeit import Timer, default_timer\nfrom typing import TypeVar\n\nfrom src.Diagonales_principales import diagonalesPrincipales1\n\nA = TypeVar('A')\n\n# 1\u00aa soluci\u00f3n\n# ===========\n\nej1: list[list[int]] = [[2,5,1,6],[4,2,5,1],[7,4,2,5],[9,7,4,2]]\nej2: list[list[int]] = [[2,5,1,6],[4,2,6,1],[7,4,2,5],[9,7,4,2]]\n\n#  esCuadrada(p) se verifica si la matriz p es cuadrada. Por ejemplo,\n#    >>> esCuadrada([[1,2],[3,4]])       == True\n#    >>> esCuadrada([[1,2],[3,4],[5,6]]) == False\n#    >>> esCuadrada([[1,2,3],[4,5,6]])   == False\ndef esCuadrada(p : list[list[A]]) -> bool:\n    return all(len(elemento) == len(p) for elemento in p)\n\n# todosIguales(xs) se verifica si todos los elementos de xs son\n# iguales. Por ejemplo,\n#    todosIguales([5,5,5])  ==  True\n#    todosIguales([5,4,5])  ==  False\ndef todosIguales(xs: list[A]) -> bool:\n    return all(x == xs[0] for x in xs)\n\ndef esToeplitz1(p: list[list[A]]) -> bool:\n    return esCuadrada(p) and all(todosIguales(xs) for xs in diagonalesPrincipales1(p))\n\n# 2\u00aa soluci\u00f3n\n# ===========\n\ndef esToeplitz2(p: list[list[A]]) -> bool:\n    n = len(p)\n    return all(len(xs) == n for xs in p) and \\\n           all(p[i][j] == p[i+1][j+1] for i in range(0,n-1)\n                                      for j in range(0,n-1))\n\n# Verificaci\u00f3n\n# ============\n\ndef test_esToeplitz() -> None:\n    for esToeplitz in [esToeplitz1, esToeplitz2]:\n        assert esToeplitz(ej1)\n        assert not esToeplitz(ej2)\n    print(\"Verificado\")\n\n# La verificaci\u00f3n es\n#    >>> test_esToeplitz()\n#    Verificado\n\n# Comparaci\u00f3n de eficiencia\n# =========================\n\ndef tiempo(e: str) -> None:\n    \"\"\"Tiempo (en segundos) de evaluar la expresi\u00f3n e.\"\"\"\n    t = Timer(e, \"\", default_timer, globals()).timeit(1)\n    print(f\"{t:0.2f} segundos\")\n\n# La comparaci\u00f3n es\n#    >>> tiempo('esToeplitz1([[1]*2*10**3]*2*10**3)')\n#    1.52 segundos\n#    >>> tiempo('esToeplitz2([[1]*2*10**3]*2*10**3)')\n#    0.51 segundos\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Una matriz de Toeplitz es una matriz cuadrada que es constante a lo largo de las diagonales paralelas a la diagonal principal. Por ejemplo, |2 5 1 6| |2 5 1 6| |4 2 5 1| |4 2 6 1| |7 4 2 5| |7 4 2 5| |9 7 4 2| |9 7 4&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"default","_kad_post_title":"default","_kad_post_layout":"default","_kad_post_sidebar_id":"","_kad_post_content_style":"default","_kad_post_vertical_padding":"default","_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":[581],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8551"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/comments?post=8551"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8551\/revisions"}],"predecessor-version":[{"id":8552,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8551\/revisions\/8552"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=8551"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=8551"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=8551"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}