122 lines
2.3 KiB
Agda
122 lines
2.3 KiB
Agda
module Day3
|
||
|
||
import Prelude
|
||
import Node
|
||
import Aoc
|
||
|
||
Parser : U → U
|
||
Parser a = List Char → Maybe (a × List Char)
|
||
|
||
instance Monad Parser where
|
||
pure a = \ cs => Just (a, cs)
|
||
bind ma mab = \ cs => ma cs >>= uncurry mab
|
||
|
||
instance Alternative Parser where
|
||
pa <|> pb = \ cs => case pa cs of
|
||
Nothing => pb cs
|
||
res => res
|
||
|
||
fail : ∀ a. Parser a
|
||
fail = \ cs => Nothing
|
||
|
||
satisfy : (Char → Bool) → Parser Char
|
||
satisfy pred = λ cs => case cs of
|
||
Nil => Nothing
|
||
(c :: cs) => if pred c then Just (c, cs) else Nothing
|
||
|
||
match : Char → Parser Char
|
||
match d = satisfy (_==_ d)
|
||
|
||
any : Parser Char
|
||
any = satisfy (λ _ => True)
|
||
|
||
some many : ∀ a. Parser a → Parser (List a)
|
||
many p = some p <|> pure Nil
|
||
some p = do
|
||
v <- p
|
||
vs <- many p
|
||
pure (v :: vs)
|
||
|
||
pnum : Parser Int
|
||
pnum = do
|
||
chars <- many (satisfy isDigit)
|
||
if S (S (S Z)) < length chars then fail
|
||
else pure $ stringToInt $ pack chars
|
||
|
||
data Inst : U where
|
||
Mult : Int → Int → Inst
|
||
Do : Inst
|
||
Dont : Inst
|
||
|
||
mul : Parser Inst
|
||
mul = do
|
||
match 'm'
|
||
match 'u'
|
||
match 'l'
|
||
match '('
|
||
x <- pnum
|
||
match ','
|
||
y <- pnum
|
||
match ')'
|
||
pure $ Mult x y
|
||
|
||
pdo : Parser Inst
|
||
pdo = do
|
||
match 'd'
|
||
match 'o'
|
||
match '('
|
||
match ')'
|
||
pure Do
|
||
|
||
pdont : Parser Inst
|
||
pdont = do
|
||
match 'd'
|
||
match 'o'
|
||
match 'n'
|
||
match '\''
|
||
match 't'
|
||
match '('
|
||
match ')'
|
||
pure Dont
|
||
|
||
some' many' : ∀ a. Parser a → Parser (List a)
|
||
many' p = do
|
||
pure MkUnit
|
||
some' p <|> (any >> many' p) <|> pure Nil
|
||
|
||
some' p = do
|
||
v <- p
|
||
vs <- many' p
|
||
pure (v :: vs)
|
||
|
||
inst : Parser Inst
|
||
inst = mul <|> pdo <|> pdont
|
||
|
||
pfile : Parser (List Inst)
|
||
pfile = many' inst
|
||
|
||
value : Inst → Int
|
||
value (Mult x y) = x * y
|
||
value _ = 0
|
||
|
||
part2 : List Inst → Bool → Int → Int
|
||
part2 Nil _ acc = acc
|
||
part2 (Do :: insts) _ acc = part2 insts True acc
|
||
part2 (Dont :: insts) _ acc = part2 insts False acc
|
||
part2 (_ :: insts) False acc = part2 insts False acc
|
||
part2 (Mult x y :: insts) True acc = part2 insts True (acc + x * y)
|
||
|
||
run : String → IO Unit
|
||
run fn = do
|
||
putStrLn fn
|
||
text <- trim <$> readFile fn
|
||
let (Just (insts, Nil)) = pfile (unpack text) | _ => putStrLn "parse failed"
|
||
let part1 = foldl _+_ 0 $ map value insts
|
||
putStrLn $ "part1 " ++ show part1
|
||
putStrLn $ "part2 " ++ show (part2 insts True 0)
|
||
|
||
main : IO Unit
|
||
main = do
|
||
run "aoc2024/day3/eg.txt"
|
||
run "aoc2024/day3/input.txt"
|