-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday10.clj
48 lines (44 loc) · 1.69 KB
/
day10.clj
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
(ns clojure-solutions.day10
(:require [clojure.string :as str])
(:use [clojure-solutions.util] :reload))
(defn- valid?
"Check if a given sequence of parentheses is valid; if not, return
either the error or parens that are still needed. The algorithm is
basically
([](} -> nil ([](} -> ) [](} -> ]) ](} -> ) (} -> )) } -> :fail }
([]( -> nil ([]( -> ) []( -> ]) ]( -> ) ( -> )) -> :partial ))"
[cs]
(letfn ((go [[c & cs :as closing] [x & xs :as input]]
(let [closing-x ({\{ \}, \[ \], \( \), \< \>} x)]
(cond
;; Group ends -> remove both parens.
(= c x) (recur cs xs)
;; new group begins -> add the closing delimiter to `closing'.
(some? closing-x) (recur (cons closing-x closing) xs)
;; No group began and no group ended -> wrong closing paren.
(some? x) {:fail x}
;; End of string -> return partial results
(nil? input) {:partial closing}))))
(go [] cs)))
;; => 413733
(defn- part1 [m]
(let [score {\) 3, \] 57, \} 1197, \> 25137}]
(->> m
(filter #(elem :fail (keys %)))
(mapcat vals)
(map score)
sum)))
;; => 3354640192
(defn- part2 [m]
(let [p-score {\) 1, \] 2, \} 3, \> 4}
score #(reduce (fn [acc x] (+ (* acc 5) (p-score x))) 0 %)]
(->> m
(filter #(elem :partial (keys %)))
(mapcat vals)
(map score)
sort
(#(nth % (quot (count %) 2))))))
(defn day10 []
(let [parses (map valid? (str/split-lines (slurp "./input/day10.txt")))]
(println (part1 parses))
(println (part2 parses))))