{"id":8509,"date":"2024-03-04T06:00:09","date_gmt":"2024-03-04T04:00:09","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=8509"},"modified":"2024-03-03T19:26:05","modified_gmt":"2024-03-03T17:26:05","slug":"04-mar-24","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/04-mar-24\/","title":{"rendered":"Reiteraci\u00f3n de suma de consecutivos"},"content":{"rendered":"<p>La reiteraci\u00f3n de la suma de los elementos consecutivos de la lista [1,5,3] es 14 como se explica en el siguiente diagrama<\/p>\n<pre>\n   1 + 5 = 6\n             \\\n              ==> 14\n             \/\n   5 + 3 = 8\n<\/pre>\n<p>y la de la lista [1,5,3,4] es 29 como se explica en el siguiente diagrama<\/p>\n<pre>\n   1 + 5 = 6\n             \\\n              ==> 14\n             \/       \\\n   5 + 3 = 8          ==> 29\n             \\       \/\n              ==> 15\n             \/\n   3 + 4 = 7\n<\/pre>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"haskell\">\n   sumaReiterada :: Num a => [a] -> a\n<\/pre>\n<p>tal que (sumaReiterada xs) es la suma reiterada de los elementos consecutivos de la lista no vac\u00eda xs. Por ejemplo,<\/p>\n<pre lang=\"haskell\">\n   sumaReiterada [1,5,3]    ==  14\n   sumaReiterada [1,5,3,4]  ==  29\n<\/pre>\n<p><!--more--><\/p>\n<p><a name=\"haskell\"><\/a><\/p>\n<h2>1. Soluciones en Haskell<\/h2>\n<pre lang=\"haskell\">\nmodule Reiteracion_de_suma_de_consecutivos where\n\nimport Test.Hspec (Spec, describe, hspec, it, shouldBe)\nimport Test.QuickCheck\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada1 :: Num a => [a] -> a\nsumaReiterada1 [x] = x\nsumaReiterada1 xs  = sumaReiterada1 [x+y | (x,y) <- consecutivos xs]\n\n-- (consecutivos xs) es la lista de pares de elementos consecutivos de\n-- xs. Por ejemplo,\n--    consecutivos [1,5,3,4]  ==  [(1,5),(5,3),(3,4)]\nconsecutivos :: [a] -> [(a,a)]\nconsecutivos xs = zip xs (tail xs)\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada2 :: Num a => [a] -> a\nsumaReiterada2 [x] = x\nsumaReiterada2 xs  = sumaReiterada2 (sumaConsecutivos xs)\n\n-- (sumaConsecutivos xs) es la suma de los de pares de elementos\n-- consecutivos de xs. Por ejemplo,\n--    sumaConsecutivos [1,5,3,4]   ==  [6,8,7]\nsumaConsecutivos :: Num a => [a] -> [a]\nsumaConsecutivos xs = zipWith (+) xs (tail xs)\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada3 :: Num a => [a] -> a\nsumaReiterada3 [x] = x\nsumaReiterada3 xs  = sumaReiterada3 (zipWith (+) xs (tail xs))\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada4 :: Num a => [a] -> a\nsumaReiterada4 [x]    = x\nsumaReiterada4 (x:xs) = sumaReiterada4 (zipWith (+) (x:xs) xs)\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada5 :: Num a => [a] -> a\nsumaReiterada5 [x]       = x\nsumaReiterada5 xs@(_:ys) = sumaReiterada5 (zipWith (+) xs ys)\n\n-- 6\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada6 :: Num a => [a] -> a\nsumaReiterada6 xs =\n  head (head (dropWhile noEsUnitaria (iterate sumaConsecutivos xs)))\n\n-- (noEsUnitaria xs) se verifica si la lista xs no tiene s\u00f3lo un\n-- elemento. Por ejemplo,\n--    noEsUnitaria []     ==  True\n--    noEsUnitaria [7,5]  ==  True\n--    noEsUnitaria [7]    ==  False\nnoEsUnitaria :: [a] -> Bool\nnoEsUnitaria [_] = False\nnoEsUnitaria _   = True\n\n-- 7\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada7 :: Num a => [a] -> a\nsumaReiterada7 =\n  head . head . dropWhile (not . null . tail) . iterate sumaConsecutivos\n\n-- 8\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada8 :: Num a => [a] -> a\nsumaReiterada8 =\n  head . head . dropWhile (not . null . tail) . iterate (zipWith (+) =<< tail)\n\n-- 9\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada9 :: Num a => [a] -> a\nsumaReiterada9 = head . until ((==1) . length) (zipWith (+) <*> tail)\n\n-- 10\u00aa soluci\u00f3n\n-- ===========\n\nsumaReiterada10 :: Num a => [a] -> a\nsumaReiterada10 xs =\n  sum (zipWith (*) xs (map fromIntegral (pascal !! (length xs - 1))))\n\n-- pascal es la lista de las filas del tri\u00e1ngulo de Pascal. Por ejemplo,\n--    \u03bb> take 7 pascal\n--    [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1],[1,6,15,20,15,6,1]]\npascal :: [[Integer]]\npascal = [1] : map f pascal\n  where f xs = zipWith (+) (0:xs) (xs++[0])\n\n-- Verificaci\u00f3n\n-- ============\n\nverifica :: IO ()\nverifica = hspec spec\n\nspecG :: ([Integer] -> Integer) -> Spec\nspecG sumaReiterada = do\n  it \"e1\" $\n    sumaReiterada [1,5,3] `shouldBe` 14\n  it \"e2\" $\n    sumaReiterada [1,5,3,4] `shouldBe` 29\n\nspec :: Spec\nspec = do\n  describe \"def. 1\" $ specG sumaReiterada1\n  describe \"def. 2\" $ specG sumaReiterada2\n  describe \"def. 3\" $ specG sumaReiterada3\n  describe \"def. 4\" $ specG sumaReiterada4\n  describe \"def. 5\" $ specG sumaReiterada5\n  describe \"def. 6\" $ specG sumaReiterada6\n  describe \"def. 7\" $ specG sumaReiterada7\n  describe \"def. 8\" $ specG sumaReiterada8\n  describe \"def. 9\" $ specG sumaReiterada9\n  describe \"def. 10\" $ specG sumaReiterada10\n\n-- La verificaci\u00f3n es\n--    \u03bb> verifica\n--\n--    20 examples, 0 failures\n\n-- Equivalencia de las definiciones\n-- ================================\n\n-- La propiedad es\nprop_sumaReiterada :: [Integer] -> Property\nprop_sumaReiterada xs =\n  not (null xs) ==>\n  all (== (sumaReiterada1 xs))\n      [f xs | f <- [sumaReiterada2,\n                    sumaReiterada3,\n                    sumaReiterada4,\n                    sumaReiterada5,\n                    sumaReiterada6,\n                    sumaReiterada7,\n                    sumaReiterada8,\n                    sumaReiterada9,\n                    sumaReiterada10 ]]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_sumaReiterada\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> length (show (sumaReiterada1 [1..4000]))\n--    1208\n--    (4.84 secs, 4,444,754,000 bytes)\n--    \u03bb> length (show (sumaReiterada2 [1..4000]))\n--    1208\n--    (3.07 secs, 3,332,858,616 bytes)\n--    \u03bb> length (show (sumaReiterada3 [1..4000]))\n--    1208\n--    (3.04 secs, 3,270,112,112 bytes)\n--    \u03bb> length (show (sumaReiterada4 [1..4000]))\n--    1208\n--    (3.05 secs, 3,332,857,768 bytes)\n--    \u03bb> length (show (sumaReiterada5 [1..4000]))\n--    1208\n--    (3.08 secs, 3,332,570,672 bytes)\n--    \u03bb> length (show (sumaReiterada6 [1..4000]))\n--    1208\n--    (3.03 secs, 3,270,469,704 bytes)\n--    \u03bb> length (show (sumaReiterada7 [1..4000]))\n--    1208\n--    (3.03 secs, 3,270,598,416 bytes)\n--    \u03bb> length (show (sumaReiterada8 [1..4000]))\n--    1208\n--    (3.14 secs, 3,202,183,352 bytes)\n--    \u03bb> length (show (sumaReiterada9 [1..4000]))\n--    1208\n--    (3.71 secs, 2,869,137,232 bytes)\n--    \u03bb> length (show (sumaReiterada10 [1..4000]))\n--    1208\n--    (6.48 secs, 4,621,303,752 bytes)\n<\/pre>\n<p><a name=\"python\"><\/a><\/p>\n<h2>2. Soluciones en Python<\/h2>\n<pre lang=\"python\">\nfrom sys import setrecursionlimit\nfrom timeit import Timer, default_timer\nfrom typing import TypeVar\n\nfrom hypothesis import given\nfrom hypothesis import strategies as st\n\nA = TypeVar('A')\nsetrecursionlimit(10**6)\n\n# 1\u00aa soluci\u00f3n\n# ===========\n\n# consecutivos(xs) es la lista de pares de elementos consecutivos de\n# xs. Por ejemplo,\n#    consecutivos([1,5,3,4])  ==  [(1,5),(5,3),(3,4)]\ndef consecutivos(xs: list[A]) -> list[tuple[A, A]]:\n    return list(zip(xs, xs[1:]))\n\ndef sumaReiterada1(xs: list[int]) -> int:\n    if len(xs) == 1:\n        return xs[0]\n    return sumaReiterada1([x + y for (x, y) in consecutivos(xs)])\n\n# 2\u00aa soluci\u00f3n\n# ===========\n\n# sumaConsecutivos(xs) es la suma de los de pares de elementos\n# consecutivos de xs. Por ejemplo,\n#    sumaConsecutivos([1,5,3,4])   ==  [6,8,7]\ndef sumaConsecutivos(xs : list[int]) -> list[int]:\n    return [x + y for (x, y) in list(zip(xs, xs[1:]))]\n\ndef sumaReiterada2(xs: list[int]) -> int:\n    if len(xs) == 1:\n        return xs[0]\n    return sumaReiterada2(sumaConsecutivos(xs))\n\n# 3\u00aa soluci\u00f3n\n# ===========\n\ndef sumaReiterada3(xs: list[int]) -> int:\n    if len(xs) == 1:\n        return xs[0]\n    return sumaReiterada3([x + y for (x, y) in list(zip(xs, xs[1:]))])\n\n# Verificaci\u00f3n\n# ============\n\ndef test_sumaReiterada() -> None:\n    for sumaReiterada in [sumaReiterada1, sumaReiterada2,\n                          sumaReiterada3]:\n        assert sumaReiterada([1,5,3]) == 14\n        assert sumaReiterada([1,5,3,4]) == 29\n    print(\"Verificado\")\n\n# La verificaci\u00f3n es\n#    >>> test_sumaReiterada()\n#    Verificado\n\n# Equivalencia de las definiciones\n# ================================\n\n# La propiedad es\n@given(st.lists(st.integers(), min_size=1))\ndef test_sumaReiterada_equiv(xs: list[int]) -> None:\n    r = sumaReiterada1(xs)\n    assert sumaReiterada2(xs) == r\n    assert sumaReiterada3(xs) == r\n\n# La comprobaci\u00f3n es\n#    >>> test_sumaReiterada_equiv()\n#    >>>\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('sumaReiterada1(range(4000))')\n#    2.18 segundos\n#    >>> tiempo('sumaReiterada2(range(4000))')\n#    1.90 segundos\n#    >>> tiempo('sumaReiterada3(range(4000))')\n#    1.97 segundos\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>La reiteraci\u00f3n de la suma de los elementos consecutivos de la lista [1,5,3] es 14 como se explica en el siguiente diagrama 1 + 5 = 6 \\ ==> 14 \/ 5 + 3 = 8 y la de la lista [1,5,3,4] es 29 como se explica en el siguiente diagrama 1 + 5 =&#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\/8509"}],"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=8509"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8509\/revisions"}],"predecessor-version":[{"id":8510,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8509\/revisions\/8510"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=8509"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=8509"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=8509"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}