Files
newt/aoc2024/Day3.newt
2024-12-03 16:36:52 -08:00

122 lines
2.3 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 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"