/ 2025 / 4 / p1.hs
p1.hs
 1  import Data.List ((!?))
 2  import Text.Parsec
 3  
 4  surrounding x y =
 5    [ (x - 1, y - 1),
 6      (x, y - 1),
 7      (x + 1, y - 1),
 8      (x - 1, y),
 9      (x + 1, y),
10      (x - 1, y + 1),
11      (x, y + 1),
12      (x + 1, y + 1)
13    ]
14  
15  at grid x y = case ((grid !? y) >>= (!? x)) of
16    Just ch -> ch
17    Nothing -> '.'
18  
19  isBlocked grid (x, y) = at grid x y == '@'
20  
21  answer input =
22    length
23      [ 1 | y <- [0 .. length grid - 1],
24            x <- [0 .. (length $ grid !! y) - 1],
25            at grid x y == '@',
26            (length $ filter (isBlocked grid) $ surrounding x y) < 4
27      ]
28    where
29      Right grid = parse ((many $ oneOf "@.") `sepEndBy` char '\n') "" input
30  
31  main = getContents >>= print . answer