From b315cc6d7918f789139e633086ca365ca236464c Mon Sep 17 00:00:00 2001 From: Amneesh Singh Date: Thu, 12 Dec 2024 22:57:08 +0530 Subject: [PATCH] day 12 Signed-off-by: Amneesh Singh --- aoc2024.cabal | 6 +++++ src/Day12.hs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/Day12.hs diff --git a/aoc2024.cabal b/aoc2024.cabal index 4eb0ea4..3191d13 100644 --- a/aoc2024.cabal +++ b/aoc2024.cabal @@ -96,3 +96,9 @@ executable day11 hs-source-dirs: src main-is: Day11.hs build-depends: containers + +executable day12 + import: common + hs-source-dirs: src + main-is: Day12.hs + build-depends: containers diff --git a/src/Day12.hs b/src/Day12.hs new file mode 100644 index 0000000..97ee6b4 --- /dev/null +++ b/src/Day12.hs @@ -0,0 +1,70 @@ +module Main where + +import qualified Data.Map as M +import qualified Data.Set as S + +type Coord = (Int, Int) + +type Grid = M.Map Coord Char + +type Region = S.Set Coord + +neighbours :: Coord -> [Coord] +neighbours (x, y) = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)] + +regions :: Grid -> [Region] +regions m + | Just (c, ch) <- M.lookupMin m = + let r = region m c ch + in r : regions (M.withoutKeys m r) + | otherwise = [] + where + region :: Grid -> (Int, Int) -> Char -> Region + region grid c ch = go c S.empty + where + -- depth first search + go :: Coord -> Region -> Region + go c s + | c `S.member` s = s + | otherwise = + let s' = S.insert c s + nexts = [n | n <- neighbours c, M.lookup n grid == Just ch] + in foldr go s' nexts + +perimeter :: Region -> Int +perimeter r = S.foldl (\a -> (+ a) <$> length . filter (not . (`S.member` r)) . neighbours) 0 r + +corners :: Region -> Int +corners r = sum . map corners' $ S.toList r + where + corners' :: Coord -> Int + corners' c = + let d@[_, _, n, s] = neighbours c + [nw, ne, _, _] = neighbours n + [sw, se, _, _] = neighbours s + [w', e', n', s'] = map (not . (`S.member` r)) d + [nw', ne', sw', se'] = map (not . (`S.member` r)) [nw, ne, sw, se] + in length $ + filter + id + [ n' && (e' || not ne'), + e' && (s' || not se'), + s' && (w' || not sw'), + w' && (n' || not nw') + ] + +main :: IO () +main = + do + raw <- lines <$> readFile "./inputs/day12.in" + + let grid = + M.fromList + [ ((x, y), ch) + | (y, row) <- zip [0 ..] raw, + (x, ch) <- zip [0 ..] row + ] + rs = regions grid + + putStr "Part 1: " >> print (sum . map ((*) <$> perimeter <*> S.size) $ rs) + putStr "Part 2: " >> print (sum . map ((*) <$> corners <*> S.size) $ rs)