···
3
+
import qualified Data.Map as Map
4
+
import Data.Map (Map)
6
+
type Grid = Map (Int,Int) Char
8
+
enumerate :: [a] -> [(Int,a)]
9
+
enumerate l = zip [0..] l
11
+
addRow :: Int -> String -> Grid -> Grid
14
+
(\g (x,c) -> Map.insert (x,y) c g)
18
+
parse :: String -> Grid
21
+
(\g (x,row) -> addRow x row g)
23
+
(enumerate $ lines s)
25
+
neighbors :: (Int,Int) -> [(Int,Int)]
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)]
29
+
isOccupied :: Grid -> (Int,Int) -> Bool
30
+
isOccupied grid p = Map.lookup p grid == Just '@'
32
+
isAccessible :: Grid -> (Int,Int) -> Char -> Bool
33
+
isAccessible grid p '@' =
34
+
length (filter (isOccupied grid) (neighbors p)) < 4
35
+
isAccessible _ _ _ = False
part1 :: String -> String
4
-
part1 _ = "Day 4 part 1"
39
+
let grid = parse input
42
+
Map.filterWithKey (isAccessible grid) grid
44
+
removeAccessible :: Grid -> Grid
45
+
removeAccessible grid =
46
+
let accessible = Map.filterWithKey (isAccessible grid) grid
47
+
in Map.difference grid accessible
49
+
removeAll :: Grid -> Grid
51
+
let grids = iterate removeAccessible grid
52
+
stabilized (x : y : gs) =
53
+
if Map.size x == Map.size y then
part2 :: String -> String
7
-
part2 _ = "Day 4 part 2"
61
+
let grid = parse input
62
+
in show $ Map.size $ Map.difference grid (removeAll grid)