Ir al contenido principal

Distancia entre dos puntos

Definir la función

   distancia :: (Double,Double) -> (Double,Double) -> Double

tal que (distancia p1 p2) es la distancia entre los puntos p1 y p2. Por ejemplo,

   distancia (1,2) (4,6)  ==  5.0

Comprobar con QuickCheck que se verifica la propiedad triangular de la distancia; es decir, dados tres puntos p1, p2 y p3, la distancia de p1 a p3 es menor o igual que la suma de la distancia de p1 a p2 y la de p2 a p3.

Soluciones

A continuación se muestran las soluciones en Haskell y las soluciones en Python.

Soluciones en Haskell

import Test.QuickCheck

distancia :: (Double,Double) -> (Double,Double) -> Double
distancia (x1,y1) (x2,y2) = sqrt((x1-x2)^2+(y1-y2)^2)

-- La propiedad es
prop_triangular :: (Double,Double) -> (Double,Double) -> (Double,Double)
                -> Property
prop_triangular p1 p2 p3 =
    all acotado [p1, p2, p3] ==>
    distancia p1 p3 <= distancia p1 p2 + distancia p2 p3
    where acotado (x, y) = abs x < cota && abs y < cota
          cota = 2^30

-- La comprobación es
--    ghci> quickCheck prop_triangular
--    +++ OK, passed 100 tests.

-- Nota: Por problemas de redondeo, la propiedad no se cumple en
-- general. Por ejemplo,
--    λ> p1 = (0, 9147936743096483)
--    λ> p2 = (0, 3)
--    λ> p3 = (0, 2)
--    λ> distancia p1 p3 <= distancia p1 p2 + distancia p2 p3
--    False
--    λ> distancia p1 p3
--    9.147936743096482e15
--    λ> distancia p1 p2 + distancia p2 p3
--    9.14793674309648e15

El código se encuentra en GitHub.

Soluciones en Python

from math import sqrt
from hypothesis import given, strategies as st

def distancia(p1: tuple[float, float],
              p2: tuple[float, float]) -> float:
    (x1, y1) = p1
    (x2, y2) = p2
    return sqrt((x1-x2)**2+(y1-y2)**2)

# La propiedad es
cota = 2 ** 30

@given(st.tuples(st.integers(min_value=0, max_value=cota),
                 st.integers(min_value=0, max_value=cota)),
       st.tuples(st.integers(min_value=0, max_value=cota),
                 st.integers(min_value=0, max_value=cota)),
       st.tuples(st.integers(min_value=0, max_value=cota),
                 st.integers(min_value=0, max_value=cota)))
def test_triangular(p1, p2, p3):
    assert distancia(p1, p3) <= distancia(p1, p2) + distancia(p2, p3)

# La comprobación es
#    src> poetry run pytest -q distancia_entre_dos_puntos.py
#    1 passed in 0.38s

# Nota: Por problemas de redondeo, la propiedad no se cumple en
# general. Por ejemplo,
#    λ> p1 = (0, 9147936743096483)
#    λ> p2 = (0, 3)
#    λ> p3 = (0, 2)
#    λ> distancia(p1, p3) <= distancia(p1, p2) + distancia (p2. p3)
#    False
#    λ> distancia(p1, p3)
#    9147936743096482.0
#    λ> distancia(p1, p2) + distancia(p2, p3)
#    9147936743096480.05

El código se encuentra en GitHub.

Comentarios

  • La raíz cuadrada de x se escribe
  • en Haskell, como sqrt x y
  • en Python, como sqrt(x) y hay que importarla del módulo math.