Files
newt/playground/samples/Day2.newt

102 lines
2.6 KiB
Agda
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module Day2
import Prelude
Draw : U
Draw = Int × Int × Int
data Game : U where
MkGame : Int -> List Draw -> Game
-- Original had class and instance...
-- Add, Sub, Mul, Neg
-- NB this is not lazy!
infixl 5 _&&_
_&&_ : Bool -> Bool -> Bool
a && b = case a of
False => False
True => b
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)`
mapM : {a b c : U} -> (a -> Either b c) -> List a -> Either b (List c)
mapM f Nil = Right Nil
mapM f (x :: xs) = case f x of
Left msg => Left msg
Right v => case mapM f xs of
Left msg => Left msg
Right vs => Right $ v :: vs
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
parseDraw : String -> Either String Draw
parseDraw line = case mapM parseColor $ split line ", " of
Right parts => Right $ foldl maxd (0,0,0) parts
Left err => Left err
parseGame : String -> Either String Game
parseGame line =
-- Need the Idris | sugar...
case split line ": " of
-- this is splitting on the Nil instead of the a
(a :: b :: Nil) => case split a " " of
("Game" :: ns :: Nil) =>
let num = toInt ns in
case mapM parseDraw $ split b "; " of
Right parts => Right $ MkGame num parts
Left err => Left err
_ => Left "No Game"
_ => Left $ "No colon in " ++ line
part1 : List Game -> Int
part1 Nil = 0
part1 (MkGame n parts :: rest) =
let total = foldl maxd (0,0,0) parts in
case lte total (12,13,14) of
True => n + part1 rest
False => part1 rest
part2 : List Game -> Int
part2 Nil = 0
part2 (MkGame n parts :: rest) =
case foldl maxd (0,0,0) parts of
(a,b,c) => a * b * c + part2 rest
-- readFile not in browser / playground
-- run : String -> IO Unit
-- run fn = do
-- text <- readFile fn
-- case mapM parseGame (split (trim text) "\n") of
-- Left err => putStrLn $ "fail " ++ err
-- Right games => do
-- 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"