Move History

Fork Selected
  • Code
    module Codewars.GetClosestPoint where
    
    type Point = (Float, Float)
    
    dist :: Point -> Point -> Float
    dist (x1, x2) (y1, y2)
      = sqrt (dx ^ 2 + dy ^ 2)
      where (dx, dy) = (y1 - x1, y2 - x2)
    
    closestPoint :: Point -> [Point] -> Point
    closestPoint point [p] = p
    closestPoint point (p : ps)
      = closestBetweenTwo point p (dist point p) (closestPoint point ps)
      where
        closestBetweenTwo :: Point -> Point -> Float -> Point -> Point
        closestBetweenTwo p0 p1 initialDist p2
          | initialDist < dist point p2 = p1
          | otherwise                   = p2
          
    closestPoint' :: Point -> [Point] -> Point
    closestPoint' point [] = point
    closestPoint' point (p : ps)
      = closestBetweenTwo point p (dist point p) ps
      where
        closestBetweenTwo :: Point -> Point -> Float -> [Point] -> Point
        closestBetweenTwo p0 p1 initialDist [] = p1
        closestBetweenTwo p0 p1 initialDist (p2 : ps)
          | initialDist < dis = closestBetweenTwo p0 p1 initialDist ps
          | otherwise         = closestBetweenTwo p0 p2 dis ps
          where dis = dist p0 p2
    Test Cases
    module Codewars.GetClosestPointSpec where
    
    import Codewars.GetClosestPoint (closestPoint, closestPoint')
    import Test.Hspec
    import Test.QuickCheck
    
    spec :: Spec
    spec = do
        describe "Points" $ do
          it "finds the closest Point" $ do
            let points = [(38, 19), (833, 938), (83, 49), (83, 83), (72, 15)]
            closestPoint (0, 0) points `shouldBe` (38, 19)
            closestPoint' (0, 0) points `shouldBe` (38, 19)
    
    -- the following line is optional for 8.2
    -- main = hspec spec