{"id":7392,"date":"2022-09-26T06:00:36","date_gmt":"2022-09-26T04:00:36","guid":{"rendered":"http:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=7392"},"modified":"2022-12-14T14:23:01","modified_gmt":"2022-12-14T12:23:01","slug":"numeros-libres-de-cuadrados","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/numeros-libres-de-cuadrados\/","title":{"rendered":"N\u00fameros libres de cuadrados"},"content":{"rendered":"<p>Un n\u00famero es libre de cuadrados si no es divisible por el cuadrado de ning\u00fan entero mayor que 1. Por ejemplo, 70 es libre de cuadrado porque s\u00f3lo es divisible por 1, 2, 5, 7 y 70; en cambio, 40 no es libre de cuadrados porque es divisible por 2^2.<\/p>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   libreDeCuadrados :: Integer -> Bool\n<\/pre>\n<p>tal que <code>libreDeCuadrados x<\/code> se verifica si <code>x<\/code> es libre de cuadrados. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   libreDeCuadrados 70  ==  True\n   libreDeCuadrados 40  ==  False\n   libreDeCuadrados (product (take 30000 primes))  ==  True\n<\/pre>\n<p><b>Soluciones<\/b><\/p>\n<p>A continuaci\u00f3n se muestran las <a href=\"#haskell\">soluciones en Haskell<\/a> y las <a href=\"#python\">soluciones en Python<\/a>.<\/p>\n<p><a name=\"haskell\"><\/a><br \/>\n<b>Soluciones en Haskell<\/b><\/p>\n<pre lang=\"haskell\">\nimport Data.List (nub)\nimport Data.Numbers.Primes (primeFactors, primes)\nimport Test.QuickCheck\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nlibreDeCuadrados1 :: Integer -> Bool\nlibreDeCuadrados1 n =\n  null [x | x <- [2..n], rem n (x^2) == 0]\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nlibreDeCuadrados2 :: Integer -> Bool\nlibreDeCuadrados2 x =\n  x == product (divisoresPrimos2 x)\n\n-- (divisoresPrimos x) es la lista de los divisores primos de x. Por\n-- ejemplo,\n--    divisoresPrimos 40 == [2,5]\n--    divisoresPrimos 70 == [2,5,7]\ndivisoresPrimos2 :: Integer -> [Integer]\ndivisoresPrimos2 x = [n | n <- divisores2 x, primo2 n]\n\n-- (divisores n) es la lista de los divisores del n\u00famero n. Por ejemplo,\n--    divisores 25  ==  [1,5,25]\n--    divisores 30  ==  [1,2,3,5,6,10,15,30]\ndivisores2 :: Integer -> [Integer]\ndivisores2 n = [x | x <- [1..n], n `mod` x == 0]\n\n-- (primo n) se verifica si n es primo. Por ejemplo,\n--    primo 30  == False\n--    primo 31  == True\nprimo2 :: Integer -> Bool\nprimo2 n = divisores2 n == [1, n]\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nlibreDeCuadrados3 :: Integer -> Bool\nlibreDeCuadrados3 n\n  | even n = n `mod` 4 \/= 0 && libreDeCuadrados3 (n `div` 2)\n  | otherwise = aux n [3,5..n]\n  where aux 1 _  = True\n        aux _ [] = True\n        aux m (x:xs)\n          | m `mod` x == 0 = m `mod` (x^2) \/= 0 && aux (m `div` x) xs\n          | otherwise      = aux m xs\n\n-- 4\u00aa soluci\u00f3n\n-- ===========\n\nlibreDeCuadrados4 :: Integer -> Bool\nlibreDeCuadrados4 x =\n  x == product (divisoresPrimos4 x)\n\ndivisoresPrimos4 :: Integer -> [Integer]\ndivisoresPrimos4 = nub . primeFactors\n\n-- 5\u00aa soluci\u00f3n\n-- ===========\n\nlibreDeCuadrados5 :: Integer -> Bool\nlibreDeCuadrados5 =\n  sinRepetidos . primeFactors\n\n-- (sinRepetidos xs) se verifica si xs no tiene elementos repetidos. Por\n-- ejemplo,\n--    sinRepetidos [3,2,5]  ==  True\n--    sinRepetidos [3,2,5,2]  ==  False\nsinRepetidos :: [Integer] -> Bool\nsinRepetidos xs =\n  nub xs == xs\n\n-- Comprobaci\u00f3n de equivalencia\n-- ============================\n\n-- La propiedad es\nprop_libreDeCuadrados :: Integer -> Property\nprop_libreDeCuadrados x =\n  x > 1 ==>\n  all (== libreDeCuadrados1 x)\n      [libreDeCuadrados2 x,\n       libreDeCuadrados3 x,\n       libreDeCuadrados4 x,\n       libreDeCuadrados5 x]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_libreDeCuadrados\n--    +++ OK, passed 100 tests; 165 discarded.\n\n-- Comparaci\u00f3n de eficiencia\n-- =========================\n\n-- La comparaci\u00f3n es\n--    \u03bb> libreDeCuadrados1 9699690\n--    True\n--    (8.54 secs, 6,441,144,248 bytes)\n--    \u03bb> libreDeCuadrados2 9699690\n--    True\n--    (4.78 secs, 1,940,781,632 bytes)\n--    \u03bb> libreDeCuadrados3 9699690\n--    True\n--    (0.01 secs, 561,400 bytes)\n--    \u03bb> libreDeCuadrados4 9699690\n--    True\n--    (0.01 secs, 568,160 bytes)\n--    \u03bb> libreDeCuadrados5 9699690\n--    True\n--    (0.01 secs, 567,536 bytes)\n--\n--    \u03bb> libreDeCuadrados3 (product (take 30000 primes))\n--    True\n--    (2.30 secs, 2,369,316,208 bytes)\n--    \u03bb> libreDeCuadrados4 (product (take 30000 primes))\n--    True\n--    (6.68 secs, 4,565,617,408 bytes)\n--    \u03bb> libreDeCuadrados5 (product (take 30000 primes))\n--    True\n--    (5.54 secs, 3,411,701,752 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Numeros_libres_de_cuadrados.hs\">GitHub<\/a>.<\/p>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom timeit import Timer, default_timer\nfrom sys import setrecursionlimit\nfrom sympy import primefactors, primerange\nfrom hypothesis import given, strategies as st\n\nsetrecursionlimit(10**6)\n\n# 1\u00aa soluci\u00f3n\n# ===========\n\ndef libreDeCuadrados1(n: int) -> bool:\n    return [x for x in range(2, n + 2) if n % (x**2) == 0] == []\n\n# 2\u00aa soluci\u00f3n\n# ===========\n\n# divisores(n) es la lista de los divisores del n\u00famero n. Por ejemplo,\n#    divisores(30)  ==  [1,2,3,5,6,10,15,30]\ndef divisores1(n: int) -> list[int]:\n    return [x for x in range(1, n + 1) if n % x == 0]\n\n# primo(n) se verifica si n es primo. Por ejemplo,\n#    primo(30)  == False\n#    primo(31)  == True\ndef primo1(n: int) -> bool:\n    return divisores1(n) == [1, n]\n\n# divisoresPrimos(x) es la lista de los divisores primos de x. Por\n# ejemplo,\n#    divisoresPrimos(40) == [2, 5]\n#    divisoresPrimos(70) == [2, 5, 7]\ndef divisoresPrimos1(x: int) -> list[int]:\n    return [n for n in divisores1(x) if primo1(n)]\n\n# producto(xs) es el producto de los elementos de xs. Por ejemplo,\n#    producto([3, 2, 5])  ==  30\ndef producto(xs):\n    if xs:\n        return xs[0] * producto(xs[1:])\n    return 1\n\ndef libreDeCuadrados2(x):\n    return x == producto(divisoresPrimos1(x))\n\n# 3\u00aa soluci\u00f3n\n# ===========\n\ndef libreDeCuadrados3(n: int) -> bool:\n    if n % 2 == 0:\n        return n % 4 != 0 and libreDeCuadrados3(n \/\/ 2)\n\n    def aux(m, xs):\n        if m == 1:\n            return True\n        if xs == []:\n            return True\n        if m % xs[0] == 0:\n            return m % (xs[0]**2) != 0 and aux(m \/\/ xs[0], xs[1:])\n        return aux(m, xs[1:])\n    return aux(n, range(3, n + 1, 2))\n\n# 4\u00aa soluci\u00f3n\n# ===========\n\ndef libreDeCuadrados4(x):\n    return x == producto(primefactors(x))\n\n# Comprobaci\u00f3n de equivalencia\n# ============================\n\n# La propiedad es\n@given(st.integers(min_value=2, max_value=1000))\ndef test_libreDeCuadrados(n):\n    assert libreDeCuadrados1(n) ==\\\n           libreDeCuadrados2(n) ==\\\n           libreDeCuadrados3(n) ==\\\n           libreDeCuadrados4(n)\n\n# La comprobaci\u00f3n es\n#    src> poetry run pytest -q numeros_libres_de_cuadrados.py\n#    1 passed in 0.59s\n\n# Comparaci\u00f3n de eficiencia\n# =========================\n\ndef tiempo(e):\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('libreDeCuadrados1(9699690)')\n#    2.66 segundos\n#    >>> tiempo('libreDeCuadrados2(9699690)')\n#    2.58 segundos\n#    >>> tiempo('libreDeCuadrados3(9699690)')\n#    0.00 segundos\n#    >>> tiempo('libreDeCuadrados4(9699690)')\n#    0.00 segundos\n#\n#    >>> n = producto(list(primerange(1, 25000)))\n#    >>> tiempo('libreDeCuadrados3(n)')\n#    0.42 segundos\n#    >>> tiempo('libreDeCuadrados4(n)')\n#    0.14 segundos\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium-Python\/blob\/main\/src\/numeros_libres_de_cuadrados.py\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un n\u00famero es libre de cuadrados si no es divisible por el cuadrado de ning\u00fan entero mayor que 1. Por ejemplo, 70 es libre de cuadrado porque s\u00f3lo es divisible por 1, 2, 5, 7 y 70; en cambio, 40 no es libre de cuadrados porque es divisible por 2^2. Definir la funci\u00f3n libreDeCuadrados ::&#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":"","_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":[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\/7392"}],"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=7392"}],"version-history":[{"count":3,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/7392\/revisions"}],"predecessor-version":[{"id":7684,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/7392\/revisions\/7684"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=7392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=7392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=7392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}