79 lines
2.3 KiB
Agda
79 lines
2.3 KiB
Agda
module Day11
|
||
|
||
import Prelude
|
||
import Node
|
||
import Aoc
|
||
import Data.SortedMap
|
||
import Monad.State
|
||
|
||
Graph : U
|
||
Graph = SortedMap String (List String)
|
||
|
||
part1 : Graph → Int
|
||
part1 g = fst $ (count "you").runState emptyMap
|
||
where
|
||
count : String → State (SortedMap String Int) Int
|
||
count "out" = pure 1
|
||
count node = do
|
||
st <- get
|
||
case lookupMap' node st of
|
||
Just v => pure v
|
||
Nothing => do
|
||
let (Just nodes) = lookupMap' node g | _ => trace "\{show node} missing" $ pure 0
|
||
counts <- traverse count nodes
|
||
let total = foldl _+_ 0 counts
|
||
modify $ updateMap node total
|
||
pure total
|
||
|
||
data Result = MkRes Int Int Int Int
|
||
|
||
emptyResult : Result
|
||
emptyResult = MkRes 0 0 0 0
|
||
|
||
part2 : Graph → Int
|
||
part2 g =
|
||
let (MkRes none dac fft both) = fst $ (count "svr").runState emptyMap in both
|
||
where
|
||
addCount : String → Result → Result → Result
|
||
addCount "fft" (MkRes n d f b) (MkRes n' d' f' b') = MkRes n (d) (f + f' + n') (b + b' + d')
|
||
addCount "dac" (MkRes n d f b) (MkRes n' d' f' b') = MkRes n (d + d' + n') (f) (b + b' + f')
|
||
addCount _ (MkRes n d f b) (MkRes n' d' f' b') = MkRes (n + n') (d + d') (f + f') (b + b')
|
||
|
||
count : String → State (SortedMap String Result) Result
|
||
count "out" = pure $ MkRes 1 0 0 0
|
||
count node = do
|
||
st <- get
|
||
case lookupMap' node st of
|
||
Just v => pure v
|
||
Nothing => do
|
||
let (Just nodes) = lookupMap' node g | _ => trace "\{show node} missing" $ pure $ MkRes 0 0 0 0
|
||
counts <- traverse count nodes
|
||
let total = foldl (addCount node) emptyResult counts
|
||
modify $ updateMap node total
|
||
pure total
|
||
|
||
parse : String → Either String Graph
|
||
parse text = do
|
||
let lines = split (trim text) "\n"
|
||
nodes <- traverse parseNode lines
|
||
pure $ mapFromList $ nodes
|
||
where
|
||
parseNode : String → Either String (String × List String)
|
||
parseNode txt = case split txt ": " of
|
||
(a :: b :: Nil) => Right (a, split b " ")
|
||
x => Left "\{show $ length x} parts"
|
||
|
||
run : String -> IO Unit
|
||
run fn = do
|
||
putStrLn fn
|
||
text <- readFile fn
|
||
let (Right graph) = parse text | Left err => putStrLn err
|
||
putStrLn $ "part1 " ++ show (part1 graph)
|
||
putStrLn $ "part2 " ++ show (part2 graph)
|
||
|
||
main : IO Unit
|
||
main = do
|
||
run "aoc2025/day11/eg.txt"
|
||
run "aoc2025/day11/eg2.txt"
|
||
run "aoc2025/day11/input.txt"
|