Haskell
Oh, this one was easy (dynamic programming at last!). Still haven't figured out the right way to approach yesterday's part two, though.
import Data.List
import Data.Map (Map)
import Data.Map qualified as Map
readInput =
Map.fromList
. map ((\(name : outs) -> (init name, outs)) . words)
. lines
part1 input = go "you"
where
go "out" = 1
go name = maybe 0 (sum . map go) $ input Map.!? name
part2 input = let (both, _, _, _) = pathsFrom "svr" in both
where
pathsFrom =
(Map.!)
. Map.insert "out" (0, 0, 0, 1)
. Map.fromList
. (zip <*> map findPaths)
$ Map.keys input ++ concat (Map.elems input)
findPaths n =
let (both, dac, fft, none) =
unzip4 $ maybe [] (map pathsFrom) (input Map.!? n)
in case n of
"dac" -> (sum both + sum fft, sum dac + sum none, 0, 0)
"fft" -> (sum both + sum dac, 0, sum fft + sum none, 0)
_ -> (sum both, sum dac, sum fft, sum none)
main = do
input <- readInput <$> readFile "input11"
print $ part1 input
print $ part2 input