import Graphics.Gnuplot.Simple
-- Definición de ternasPitagoricas
-- ===============================
ternasPitagoricas :: Integer -> [(Integer,Integer,Integer)]
ternasPitagoricas x =
[(x,y,z) | y <- [1..(x^ 2 - 1) `div` 2 ]
, z <- raizCuadrada (x^2 + y^2)]
-- La justificación de la cota es
-- x > 2
-- x^2 + y^2 >= (y+1)^2
-- x^2 + y^2 >= y^2 + 2*y + 1
-- y =< (x^ 2 - 1) `div` 2
-- (raizCuadrada x) es la lista formada por la raíz cuadrada entera de
-- x, si existe y la lista vacía, en caso contrario. Por ejemplo,
-- raizCuadrada 25 == [5]
-- raizCuadrada 26 == []
raizCuadrada :: Integer -> [Integer]
raizCuadrada x =
[y | y <- [(round . sqrt . fromIntegral) x]
, y^2 == x]
-- 1ª definición de mayorTernaPitagorica
-- =====================================
mayorTernaPitagorica :: Integer -> (Integer,Integer,Integer)
mayorTernaPitagorica =
last . ternasPitagoricas
-- 2ª definición de mayorTernaPitagorica
-- =====================================
mayorTernaPitagorica2 :: Integer -> (Integer,Integer,Integer)
mayorTernaPitagorica2 x =
head [(x,y,z) | y <- [k, k-1 .. 1]
, z <- raizCuadrada (x^2 + y^2)]
where k = (x^2 - 1) `div` 2
-- 3ª definición de mayorTernaPitagorica
-- =====================================
-- Se supone que x > 2. Se consideran dos casos:
--
-- Primer caso: Supongamos que x es par. Entonces x^2 > 4 y es divisible
-- por 4. Por tanto, existe un y tal que x^2 = 4*y + 4; luego,
-- x^2 + y^2 = 4*y + 4 + y^2
-- = (y + 2)^2
-- La terna es (x,y,y+2) donde y = (x^2 - 4) / 4.
--
-- Segundo caso: Supongamos que x es impar. Entonces x^2 es impar. Por
-- tanto, existe un y tal que x^2 = 2*y + 1; luego,
-- x^2 + y^2 = 2*y + 1 + y^2
-- = (y+1)^2
-- La terna es (x,y,y+1) donde y = (x^2 - 1) / 2.
mayorTernaPitagorica3 :: Integer -> (Integer,Integer,Integer)
mayorTernaPitagorica3 x
| even x = (x, y1, y1 + 2)
| otherwise = (x, y2, y2 + 1)
where y1 = (x^2 - 4) `div` 4
y2 = (x^2 - 1) `div` 2
-- Comparación de eficiencia
-- λ> mayorTernaPitagorica 1006
-- (1006,253008,253010)
-- (7.36 secs, 1,407,793,992 bytes)
-- λ> mayorTernaPitagorica2 1006
-- (1006,253008,253010)
-- (3.76 secs, 704,007,456 bytes)
-- λ> mayorTernaPitagorica3 1006
-- (1006,253008,253010)
-- (0.01 secs, 157,328 bytes)
graficaMayorHipotenusa :: Integer -> IO ()
graficaMayorHipotenusa n =
plotList [ Key Nothing
, PNG "Terna_pitagorica_a_partir_de_un_lado.png"
]
[(x,z) | x <- [3..n]
, let (_,_,z) = mayorTernaPitagorica3 x]