Advent of Code solutions
at main 70 lines 2.1 kB view raw
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