module Day2 import Prelude import Node Draw : U Draw = Int × Int × Int data Game : U where MkGame : Int -> List Draw -> Game -- Original had class and instance... -- Add, Sub, Mul, Neg max : Int -> Int -> Int max x y = case x < y of True => y False => x pfunc repr : {a : U} -> a -> String := `(a,o) => ''+o` pfunc jrepr : {a : U} -> a -> String := `(a,o) => JSON.stringify(o, null, ' ')` pfunc toInt : String -> Int := `s => Number(s)` maxd : Draw -> Draw -> Draw maxd (a,b,c) (d,e,f) = (max a d, max b e, max c f) lte : Draw -> Draw -> Bool lte (a,b,c) (d,e,f) = a <= d && b <= e && c <= f parseColor : String -> Either String Draw parseColor line = case split line " " of (n :: "red" :: Nil) => Right (toInt n,0,0) (n :: "green" :: Nil) => Right (0,toInt n,0) (n :: "blue" :: Nil) => Right (0,0,toInt n) x => Left $ "Bad draw" ++ repr x -- FIXME implicit isn't being solved in time here. parseDraw : String -> Either String Draw parseDraw line = case mapM {Either String} parseColor $ split line ", " of Right parts => Right $ foldl maxd (0,0,0) parts Left err => Left err parseGame : String -> Either String Game parseGame line = let (a :: b :: Nil) = split line ": " | _ => Left $ "No colon in " ++ line in let ("Game" :: ns :: Nil) = split a " " | _ => Left $ "No Game" in let (Right parts) = mapM {Either String} parseDraw $ split b "; " | Left err => Left err in Right $ MkGame (toInt ns) parts part1 : List Game -> Int part1 Nil = 0 part1 (MkGame n parts :: rest) = let total = foldl maxd (0,0,0) parts in if lte total (12,13,14) then n + part1 rest else part1 rest part2 : List Game -> Int part2 Nil = 0 part2 (MkGame n parts :: rest) = let (a,b,c) = foldl maxd (0,0,0) parts in a * b * c + part2 rest run : String -> IO Unit run fn = do putStrLn fn text <- readFile fn let (Right games) = mapM {Either String} parseGame (split (trim text) "\n") | Left err => putStrLn $ "fail " ++ err putStrLn "part1" printLn (part1 games) putStrLn "part2" printLn (part2 games) main : IO Unit main = do run "aoc2023/day2/eg.txt" run "aoc2023/day2/input.txt"