-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathconcave-polygon.hs
67 lines (51 loc) · 1.85 KB
/
concave-polygon.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{-
Concave Polygon (https://www.hackerrank.com/challenges/lambda-march-concave-polygon)
FP/Recusion, Medium, 40 pts
You are given the cartesian coordinates of a set of points in a 2D plane (in no particular order).
Each of these points is a corner point of some Polygon, P, which is not self-intersecting in nature.
Can you determine whether or not P is a concave polygon?
Input Format
The first line contains an integer, N, denoting the number of points.
The N subsequent lines each contain 2 space-separated integers denoting the respective x and y coordinates of a point.
Constraints
3 <= N <= 1000
0 <= x,y <= 1000
Output Format
Print YES if P is a concave polygon; otherwise, print NO.
-}
import Data.List
import Data.Function
tau = 2*pi
bottomPoint :: [(Int, Int)] -> (Int, Int)
bottomPoint = minimumBy (compare `on` snd)
slope :: (Int, Int) -> (Int, Int) -> Double
slope (x1,y1) (x2,y2) = atan2 dy dx
where
dx = fromIntegral (x2 - x1)
dy = fromIntegral (y2 - y1)
angle :: (Int, Int) -> (Int, Int) -> (Int, Int) -> Double
angle a b c = fixup $ slope b c - slope b a
where fixup x = let y = x + tau in if y > tau then y - tau else y
comparePoints :: (Int, Int) -> (Int, Int) -> (Int, Int) -> Ordering
comparePoints o x y = case signum (slope o x - slope o y) of
-1 -> LT
0 -> (compare `on` fst) x y
_ -> GT
sortPoints :: (Int, Int) -> [(Int, Int)] -> [(Int, Int)]
sortPoints o = sortBy (comparePoints o)
isConcave :: [(Int, Int)] -> Bool
isConcave [] = False
isConcave [_] = False
isConcave [_,_] = False
isConcave ps = or $ zipWith3 concave p (rot p) (rot (rot p))
where
o = bottomPoint ps
p = sortPoints o ps
rot (x:xs) = xs ++ [x]
concave a b c = angle a b c < pi
main :: IO ()
main = do
getLine
c <- getContents
let ans = isConcave $ map ((\[x,y]->(read x, read y)) . words) $ lines c
putStrLn $ if ans then "YES" else "NO"