summaryrefslogtreecommitdiff
path: root/2020/18.hs
diff options
context:
space:
mode:
Diffstat (limited to '2020/18.hs')
-rw-r--r--2020/18.hs39
1 files changed, 39 insertions, 0 deletions
diff --git a/2020/18.hs b/2020/18.hs
new file mode 100644
index 0000000..e77ea48
--- /dev/null
+++ b/2020/18.hs
@@ -0,0 +1,39 @@
+module Main where
+
+import Text.Parsec hiding (getInput)
+import Text.Parsec.Expr
+
+import Input
+
+
+data Expr = Expr :+ Expr | Expr :* Expr | Lit Int
+ deriving (Show)
+
+eval :: Expr -> Int
+eval (a :+ b) = eval a + eval b
+eval (a :* b) = eval a * eval b
+eval (Lit n) = n
+
+type Parser = Parsec String ()
+
+data Part = Part1 | Part2
+
+parseExpr :: Part -> String -> Expr
+parseExpr part = either (error . show) id . parse pExpr ""
+ where
+ pExpr = buildExpressionParser (table part) pTerm
+ table Part1 = [[Infix (pOpers [pOperPlus, pOperMul]) AssocLeft]]
+ table Part2 = [[Infix (pOpers [pOperPlus]) AssocLeft]
+ ,[Infix (pOpers [pOperMul]) AssocLeft]]
+ pTerm = try (spaces >> ((Lit <$> pNum) <|> pParens))
+ pNum = read <$> many1 digit
+ pParens = between (char '(') (char ')') pExpr
+ pOpers os = try (spaces >> choice os) :: Parser (Expr -> Expr -> Expr)
+ pOperPlus = (:+) <$ char '+'
+ pOperMul = (:*) <$ char '*'
+
+main :: IO ()
+main = do
+ input <- getInput 18
+ print (sum (map (eval . parseExpr Part1) input))
+ print (sum (map (eval . parseExpr Part2) input))