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))