Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.40 KB | None | 0 0
  1. import Data.List
  2.  
  3. newtype Stack a = Stack [a] deriving Show
  4.  
  5. newStack :: Stack a
  6. newStack = Stack []
  7.  
  8. push :: a -> Stack a -> Stack a
  9. push x (Stack xs) = Stack (x : xs)
  10.  
  11. top :: Stack a -> Maybe a
  12. top (Stack []) = Nothing
  13. top (Stack (x:_)) = Just x
  14.  
  15. pop :: Stack a -> Stack a
  16. pop (Stack [] ) = Stack []
  17. pop (Stack (_ : xs)) = Stack xs
  18.  
  19. stackLength :: Stack a -> Int
  20. stackLength (Stack xs) = length xs
  21.  
  22. nextToTop :: Stack a -> Maybe a
  23. nextToTop (Stack []) = Nothing
  24. nextToTop (Stack (_:[])) = Nothing
  25. nextToTop (Stack (_:y:_)) = Just y
  26.  
  27. asList :: Stack a -> [a]
  28. asList (Stack xs) = xs
  29.  
  30. data Point = Cartesian Float Float
  31. deriving (Show, Ord, Eq)
  32.  
  33. ccw :: Point -> Point -> Point -> Float
  34.  
  35. ccw (Cartesian ax ay) (Cartesian bx by) (Cartesian cx cy) =
  36. (bx - ax) * (cy - ay) - (cx - ax) * (by - ay)
  37.  
  38. getLowerLeftMostPoint :: [Point] -> Maybe Point
  39. getLowerLeftMostPoint [] = Nothing
  40. getLowerLeftMostPoint points = Just (minimumBy sortFun points)
  41.  
  42. sortFun :: Point -> Point -> Ordering
  43. sortFun (Cartesian x1 y1) (Cartesian x2 y2) = case compare y1 y2 of
  44. EQ -> compare x1 x2
  45. anything -> anything
  46.  
  47. -- Euclidean distance
  48. dist :: Point -> Point -> Float
  49. dist (Cartesian x1 y1) (Cartesian x2 y2) = sqrt (f x1 x2 + f y1 y2)
  50. where f a b = (a - b) ** 2
  51.  
  52.  
  53.  
  54. testData :: [Point]
  55. testData =
  56. [ (Cartesian 0.3215348546593775 0.03629583077160248)
  57. , (Cartesian 0.02402358131857918 (-0.2356728797179394))
  58. , (Cartesian 0.04590851212470659 (-0.4156409924995536))
  59. , (Cartesian 0.3218384001607433 0.1379850698988746)
  60. , (Cartesian 0.11506479756447 (-0.1059521474930943))
  61. , (Cartesian 0.2622539999543261 (-0.29702873322836))
  62. , (Cartesian (-0.161920957418085) (-0.4055339716426413))
  63. , (Cartesian 0.1905378631228002 0.3698601009043493)
  64. , (Cartesian 0.2387090918968516 (-0.01629827079949742))
  65. , (Cartesian 0.07495888748668034 (-0.1659825110491202))
  66. , (Cartesian 0.3319341836794598 (-0.1821814101954749))
  67. , (Cartesian 0.07703635755650362 (-0.2499430638271785))
  68. , (Cartesian 0.2069242999022122 (-0.2232970760420869))
  69. , (Cartesian 0.04604079532068295 (-0.1923573186549892))
  70. , (Cartesian 0.05054295812784038 0.4754929463150845)
  71. , (Cartesian (-0.3900589168910486) 0.2797829520700341)
  72. , (Cartesian 0.3120693385713448 (-0.0506329867529059))
  73. , (Cartesian 0.01138812723698857 0.4002504701728471)
  74. , (Cartesian 0.009645149586391732 0.1060251100976254)
  75. , (Cartesian (-0.03597933197019559) 0.2953639456959105)
  76. , (Cartesian 0.1818290866742182 0.001454397571696298)
  77. , (Cartesian 0.444056063372694 0.2502497166863175)
  78. , (Cartesian (-0.05301752458607545) (-0.06553921621808712))
  79. , (Cartesian 0.4823896228171788 (-0.4776170002088109))
  80. , (Cartesian (-0.3089226845734964) (-0.06356112199235814))
  81. , (Cartesian (-0.271780741188471) 0.1810810595574612)
  82. , (Cartesian 0.4293626522918815 0.2980897964891882)
  83. , (Cartesian (-0.004796652127799228) 0.382663812844701)
  84. , (Cartesian 0.430695573269106 (-0.2995073500084759))
  85. , (Cartesian 0.1799668387323309 (-0.2973467472915973))
  86. , (Cartesian 0.4932166845474547 0.4928094162538735)
  87. , (Cartesian (-0.3521487911717489) 0.4352656197131292)
  88. , (Cartesian (-0.4907368011686362) 0.1865826865533206)
  89. , (Cartesian (-0.1047924716070224) (-0.247073392148198))
  90. , (Cartesian 0.4374961861758457 (-0.001606279519951237))
  91. , (Cartesian 0.003256207800708899 (-0.2729194320486108))
  92. , (Cartesian 0.04310378203457577 0.4452604050238248)
  93. , (Cartesian 0.4916198379282093 (-0.345391701297268))
  94. , (Cartesian 0.001675087028811806 0.1531837672490476)
  95. , (Cartesian (-0.4404289572876217) (-0.2894855991839297))
  96. ]
  97.  
  98. test :: [Point]
  99. test = graham testData
  100.  
  101. graham :: [Point] -> [Point]
  102. graham points = asList (foldl performScan newStack sortedPoints)
  103. where
  104. Just p0 = getLowerLeftMostPoint points
  105. f p1 p2 = let orientation = ccw p0 p1 p2 in
  106. case compare orientation 0 of
  107. EQ -> compare (dist p0 p1**2) (dist p0 p2**2)
  108. GT -> LT
  109. LT -> GT
  110. sortedPoints = sortBy f points
  111.  
  112. -- scan :: Stack Point -> [Point] -> Stack Point
  113. -- scan st [] = st
  114. -- scan st (x : xs) = scan (performScan st x) xs
  115.  
  116. performScan :: Stack Point -> Point -> Stack Point
  117. performScan st p0 = if (stackLength st > 1) && (ccw second first p0) < 0
  118. then performScan (pop st) p0
  119. else push p0 st
  120. where
  121. Just first = top st
  122. Just second = nextToTop st
  123.  
  124. main :: IO()
  125. main = print $ test
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement