advent-of-code/2020/day18/day18.hs

56 lines
1.9 KiB
Haskell

module Day18 where
import AoC
import Control.Applicative
import Data.Maybe
import Text.ParserCombinators.ReadP
import Text.Read.Lex
data Expression = Literal Int
| Addition Expression Expression
| Multiplication Expression Expression
| Bracketed Expression
type ApplicationSequencer = Expression -> String -> Expression -> Expression
parseLiteral :: ReadP Expression
parseLiteral = Literal <$> readDecP
parseBracketed :: ApplicationSequencer -> ReadP Expression
parseBracketed seq = Bracketed <$> between (char '(') (char ')') (parseExpression seq)
parseOperations :: ApplicationSequencer -> ReadP Expression
parseOperations seq =
do l <- parseLiteral <|> parseBracketed seq
apps <- many1 $ parseApplication seq
return $ foldl (\l (op, r) -> seq l op r) l apps
parseApplication :: ApplicationSequencer -> ReadP (String, Expression)
parseApplication seq =
do skipSpaces
op <- choice $ map string ["*", "+"]
skipSpaces
r <- parseLiteral <|> parseBracketed seq
return $ (op, r)
parseExpression :: ApplicationSequencer -> ReadP Expression
parseExpression seq = parseLiteral <|> parseOperations seq <|> parseBracketed seq
sequenceLeftToRight :: ApplicationSequencer
sequenceLeftToRight l op r = toOperation op l r
where toOperation "*" = Multiplication
toOperation "+" = Addition
sequenceAdditionPrecedence :: ApplicationSequencer
sequenceAdditionPrecedence (Multiplication l r) "+" rr = Multiplication l (Addition r rr)
sequenceAdditionPrecedence l op r = sequenceLeftToRight l op r
eval :: Expression -> Int
eval (Literal n) = n
eval (Addition l r) = eval l + eval r
eval (Multiplication l r) = eval l * eval r
eval (Bracketed x) = eval x
main = runAoC lines (run sequenceLeftToRight) (run sequenceAdditionPrecedence)
where run seq = sum . map (eval . fromJust . oneCompleteResult (parseExpression seq))