Advent of Code solutions
1import Text.Parsec
2import Data.List (sortBy, sort)
3import Control.Monad (guard)
4
5integer = read <$> many digit
6point = do
7 x :: Int <- integer
8 char ','
9 y :: Int <- integer
10 return (x, y)
11
12area ((x1, y1), (x2, y2)) = (abs (x1 - x2) + 1) * (abs (y1 - y2) + 1)
13
14isHorizontal ((_, y1), (_, y2)) = y1 == y2
15isVertical ((x1, _), (x2, _)) = x1 == x2
16
17collide (p1, p2) ((bx1, by1), (bx2, by2)) =
18 let
19 (px1, px2) = if fst p1 < fst p2 then (fst p1, fst p2) else (fst p2, fst p1)
20 (py1, py2) = if snd p1 < snd p2 then (snd p1, snd p2) else (snd p2, snd p1)
21 in px1 < bx2 && px2 > bx1 && py1 < by2 && py2 > by1
22
23containsBy key (a, b) (p1, p2) =
24 let (w, z) = if key p1 < key p2 then (key p1, key p2) else (key p2, key p1) in
25 w <= a && a <= z && w <= b && b <= z
26
27answer :: String -> Int
28answer input = best
29 where
30 Right points = parse (point `sepEndBy` char '\n') "" input
31 edges = zip ((last points) : points) points
32
33 verticals = sortBy (\a b -> compare (fst $ fst a) (fst $ fst b)) $ filter isVertical edges
34 horizontals = sortBy (\a b -> compare (snd $ fst a) (snd $ fst b)) $ filter isHorizontal edges
35
36 xs = (fst.fst) <$> verticals
37 ys = (snd.fst) <$> horizontals
38
39 min_x = head xs
40 max_x = last xs
41 min_y = head ys
42 max_y = last ys
43
44 y_ranges = zip ys (tail ys)
45 x_ranges = zip xs (tail xs)
46
47 illegal_x = do
48 range@(y1, y2) <- y_ranges
49 guard (y1 /= y2)
50 let
51 xs = (fst . fst) <$> filter (containsBy snd range) verticals
52 x1 = head xs
53 x2 = last xs
54 in [((min_x, y1), (x1, y2)), ((x2, y1), (max_x, y2))]
55
56 illegal_y = do
57 range@(x1, x2) <- x_ranges
58 guard (x1 /= x2)
59 let
60 ys = (snd . fst) <$> filter (containsBy fst range) horizontals
61 y1 = head ys
62 y2 = last ys
63 in [((x1, min_y),(x2, y1)), ((x1, y2),(x2, max_y))]
64 illegal = illegal_x ++ illegal_y
65 best :: Int = foldl max 0
66 $ fmap area
67 $ filter (\point -> not $ any (collide point) illegal)
68 $ [(points !! i, points !! j) | i <- [0..length points - 1], j <- [i + 1..length points - 1]]
69
70main = getContents >>= print . answer