about summary refs log tree commit diff
path: root/day18.clj
blob: 450969a9e3947366e239e7f7c2c83560ef45c5a4 (plain) (blame)
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(ns day18
  (:require [instaparse.core :as insta])
  (:require [clojure.core.match :refer [match]]))

(def WS
  (insta/parser "WS = #'\\s+'"))

(def transform-options
  {:IntLiteral read-string})

(def parser1
  (insta/parser
    "AddExpr = AddExpr '+' Paren | AddExpr '*' Paren | Paren
     Paren = '(' AddExpr ')' | IntLiteral
     IntLiteral = #'[0-9]+'"
    :auto-whitespace WS))

(def parser2
  (insta/parser
    "MultExpr = MultExpr '*' AddExpr | AddExpr
     AddExpr = AddExpr '+' Paren | Paren
     Paren = '(' MultExpr ')' | IntLiteral
     IntLiteral = #'[0-9]+'"
    :auto-whitespace WS))

(defn eval-expr [expr]
  (match expr
         [:MultExpr e1 "*" e2] (* (eval-expr e1) (eval-expr e2))
         [:AddExpr e1 "+" e2] (+ (eval-expr e1) (eval-expr e2))
         [:AddExpr e1 "*" e2] (* (eval-expr e1) (eval-expr e2))
         [:MultExpr e1] (eval-expr e1)
         [:AddExpr e1] (eval-expr e1)
         [:Paren e1] (eval-expr e1)
         [:Paren "(" e1 ")"] (eval-expr e1)
         :else expr))

(defn eval1 [input]
  (->> (parser1 input)
       (insta/transform transform-options)
       eval-expr))

(->> (slurp "day18")
     clojure.string/split-lines
     (map eval1)
     (apply +))
;; => 3159145843816

(defn eval2 [input]
  (->> (parser2 input)
       (insta/transform transform-options)
       eval-expr))

(->> (slurp "day18")
     clojure.string/split-lines
     (map eval2)
     (apply +))
;; => 55699621957369