summaryrefslogtreecommitdiff
path: root/2020/18.hs
blob: e77ea485ac25ac311250d0b772636732b69f2c2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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))