Advent of Code 2025
1module Day4 where 2 3import qualified Data.Map as Map 4import Data.Map (Map) 5 6type Grid = Map (Int,Int) Char 7 8enumerate :: [a] -> [(Int,a)] 9enumerate l = zip [0..] l 10 11addRow :: Int -> String -> Grid -> Grid 12addRow y row grid = 13 foldl 14 (\g (x,c) -> Map.insert (x,y) c g) 15 grid 16 (enumerate row) 17 18parse :: String -> Grid 19parse s = 20 foldl 21 (\g (x,row) -> addRow x row g) 22 Map.empty 23 (enumerate $ lines s) 24 25neighbors :: (Int,Int) -> [(Int,Int)] 26neighbors (x,y) = 27 [(x-1,y-1),(x,y-1),(x+1,y-1),(x-1,y),(x+1,y),(x-1,y+1),(x,y+1),(x+1,y+1)] 28 29isOccupied :: Grid -> (Int,Int) -> Bool 30isOccupied grid p = Map.lookup p grid == Just '@' 31 32isAccessible :: Grid -> (Int,Int) -> Char -> Bool 33isAccessible grid p '@' = 34 length (filter (isOccupied grid) (neighbors p)) < 4 35isAccessible _ _ _ = False 36 37part1 :: String -> String 38part1 input = 39 let grid = parse input 40 in show $ 41 length $ 42 Map.filterWithKey (isAccessible grid) grid 43 44removeAccessible :: Grid -> Grid 45removeAccessible grid = 46 let accessible = Map.filterWithKey (isAccessible grid) grid 47 in Map.difference grid accessible 48 49removeAll :: Grid -> Grid 50removeAll grid = 51 let grids = iterate removeAccessible grid 52 stabilized (x : y : gs) = 53 if Map.size x == Map.size y then 54 x 55 else 56 stabilized (y : gs) 57 in stabilized grids 58 59part2 :: String -> String 60part2 input = 61 let grid = parse input 62 in show $ Map.size $ Map.difference grid (removeAll grid)