80 lines
2.2 KiB
Agda
80 lines
2.2 KiB
Agda
module Day4
|
||
|
||
import Prelude
|
||
import Node
|
||
import Aoc
|
||
import Data.SortedMap
|
||
|
||
gridPoints : String → List (Char × Int × Int)
|
||
gridPoints text = go 0 0 (unpack text) Nil
|
||
where
|
||
go : Int → Int → List Char → List (Char × Int × Int) → List (Char × Int × Int)
|
||
go row col Nil points = points
|
||
go row col ('\n' :: cs) points = go (row + 1) 0 cs points
|
||
go row col (c :: cs) points = go row (col + 1) cs ((c,row,col) :: points)
|
||
|
||
Grid : U
|
||
Grid = SortedMap Point Int
|
||
|
||
getGrid : String → Grid
|
||
getGrid text = foldl update (EmptyMap compare) $ gridPoints text
|
||
where
|
||
update : Grid → Char × Point → Grid
|
||
update grid (c,pt) = updateMap pt (ord c) grid
|
||
|
||
neighbors : Point → List Point
|
||
neighbors pt = map (_+_ pt) (
|
||
(0 - 1, 0 - 1) :: (0 - 1, 0) :: (0 - 1, 1) ::
|
||
(0, 0 - 1) :: (0, 1) ::
|
||
(1, 0 - 1) :: (1, 0) :: (1, 1) :: Nil)
|
||
|
||
part1 : Grid → Int
|
||
part1 grid = go 0 $ toList grid
|
||
where
|
||
full : Maybe Int → Bool
|
||
full (Just 64) = True
|
||
full _ = False
|
||
|
||
go : Int → List (Point × Int) → Int
|
||
go acc Nil = acc
|
||
go acc ((pt,64) :: rest) =
|
||
let count = length' $ filter full $ map (flip lookupMap' grid) $ neighbors pt
|
||
in if count < 4 then go (acc + 1) rest else go acc rest
|
||
go acc (_ :: rest) = go acc rest
|
||
|
||
part2 : Grid → Int
|
||
part2 grid =
|
||
let todo = filter (\ x => snd x == 64) $ toList grid
|
||
in go todo emptyMap grid
|
||
where
|
||
full : (Point × Int) → Bool
|
||
full (_, 64) = True
|
||
full _ = False
|
||
|
||
helper : Grid → (Point × Int) → Grid
|
||
helper todo (k, v) = updateMap k v todo
|
||
|
||
go : List (Point × Int) → Grid → Grid → Int
|
||
go Nil todo grid = do
|
||
case toList todo of
|
||
Nil => length' $ filter (\ x => snd x == 0) $ toList {Point} {Int} grid
|
||
todo => go todo emptyMap grid
|
||
go ((pt, _) :: xs) todo grid = do
|
||
let pts = filter full $ mapMaybe (flip lookupMap grid) $ neighbors pt
|
||
if length' pts < 4
|
||
then go xs (foldl helper todo pts) (updateMap pt 0 grid)
|
||
else go xs todo grid
|
||
|
||
run : String -> IO Unit
|
||
run fn = do
|
||
putStrLn fn
|
||
text <- readFile fn
|
||
let grid = getGrid text
|
||
putStrLn $ "part1 " ++ show (part1 grid)
|
||
putStrLn $ "part2 " ++ show (part2 grid)
|
||
|
||
main : IO Unit
|
||
main = do
|
||
run "aoc2025/day4/eg.txt"
|
||
run "aoc2025/day4/input.txt"
|