Advent of Code solutions

2025 day 9 in hs to be fast enough

+70
+70
2025/9/p2.hs
··· 1 + import Text.Parsec 2 + import Data.List (sortBy, sort) 3 + import Control.Monad (guard) 4 + 5 + integer = read <$> many digit 6 + point = do 7 + x :: Int <- integer 8 + char ',' 9 + y :: Int <- integer 10 + return (x, y) 11 + 12 + area ((x1, y1), (x2, y2)) = (abs (x1 - x2) + 1) * (abs (y1 - y2) + 1) 13 + 14 + isHorizontal ((_, y1), (_, y2)) = y1 == y2 15 + isVertical ((x1, _), (x2, _)) = x1 == x2 16 + 17 + collide (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 + 23 + containsBy 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 + 27 + answer :: String -> Int 28 + answer 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 + 70 + main = getContents >>= print . answer