Ternas pitagórica
Una terna (x,y,z) de enteros positivos es pitagórica si x² + y² = z² y x < y < z.
Definir la función
pitagoricas :: Int -> [(Int,Int,Int)]
tal que pitagoricas n
es la lista de todas las ternas pitagóricas cuyas componentes están entre 1 y n
. Por ejemplo,
pitagoricas 10 == [(3,4,5),(6,8,10)] pitagoricas 15 == [(3,4,5),(5,12,13),(6,8,10),(9,12,15)]
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
Soluciones en Haskell
import Test.QuickCheck -- 1ª solución -- =========== pitagoricas1 :: Int -> [(Int,Int,Int)] pitagoricas1 n = [(x,y,z) | x <- [1..n] , y <- [1..n] , z <- [1..n] , x^2 + y^2 == z^2 , x < y && y < z] -- 2ª solución -- =========== pitagoricas2 :: Int -> [(Int,Int,Int)] pitagoricas2 n = [(x,y,z) | x <- [1..n] , y <- [x+1..n] , z <- [ceiling (sqrt (fromIntegral (x^2+y^2)))..n] , x^2 + y^2 == z^2] -- 3ª solución -- =========== pitagoricas3 :: Int -> [(Int,Int,Int)] pitagoricas3 n = [(x,y,z) | x <- [1..n] , y <- [x+1..n] , let z = round (sqrt (fromIntegral (x^2+y^2))) , y < z , z <= n , x^2 + y^2 == z^2] -- Comprobación de equivalencia -- ============================ -- La propiedad es prop_pitagoricas :: Positive Int -> Bool prop_pitagoricas (Positive n) = all (== pitagoricas1 n) [pitagoricas2 n, pitagoricas3 n] -- La comprobación es -- λ> quickCheck prop_pitagoricas -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> length (pitagoricas1 200) -- 127 -- (12.25 secs, 12,680,320,400 bytes) -- λ> length (pitagoricas2 200) -- 127 -- (1.61 secs, 1,679,376,824 bytes) -- λ> length (pitagoricas3 200) -- 127 -- (0.06 secs, 55,837,072 bytes)
El código se encuentra en GitHub.
Soluciones en Python
from math import ceil, sqrt from timeit import Timer, default_timer from hypothesis import given from hypothesis import strategies as st # 1ª solución # =========== def pitagoricas1(n: int) -> list[tuple[int, int, int]]: return [(x, y, z) for x in range(1, n+1) for y in range(1, n+1) for z in range(1, n+1) if x**2 + y**2 == z**2 and x < y < z] # 2ª solución # =========== def pitagoricas2(n: int) -> list[tuple[int, int, int]]: return [(x, y, z) for x in range(1, n+1) for y in range(x+1, n+1) for z in range(ceil(sqrt(x**2+y**2)), n+1) if x**2 + y**2 == z**2] # 3ª solución # =========== def pitagoricas3(n: int) -> list[tuple[int, int, int]]: return [(x, y, z) for x in range(1, n+1) for y in range(x+1, n+1) for z in [ceil(sqrt(x**2+y**2))] if y < z <= n and x**2 + y**2 == z**2] # Comprobación de equivalencia # ============================ # La propiedad es @given(st.integers(min_value=1, max_value=50)) def test_pitagoricas(n: int) -> None: r = pitagoricas1(n) assert pitagoricas2(n) == r assert pitagoricas3(n) == r # La comprobación es # src> poetry run pytest -q ternas_pitagoricas.py # 1 passed in 1.83s # Comparación de eficiencia de pitagoricas # ====================================== def tiempo(e: str) -> None: """Tiempo (en segundos) de evaluar la expresión e.""" t = Timer(e, "", default_timer, globals()).timeit(1) print(f"{t:0.2f} segundos") # La comparación es # >>> tiempo('pitagoricas1(200)') # 4.76 segundos # >>> tiempo('pitagoricas2(200)') # 0.69 segundos # >>> tiempo('pitagoricas3(200)') # 0.02 segundos
El código se encuentra en GitHub.