[download] []
 
(ns advent-of-code-2021.day10
  (:require  [clojure.java.io :as io]
             [clojure.string :as str]))

(let [lines (->> "day10/input.txt"
                 io/resource
                 slurp
                 str/split-lines
                 (mapv (partial into [])))
      bracket-pairs {\[ \] \{ \} \( \) \< \>}
      open-brackets (into #{} (keys bracket-pairs))

      consume-next-bracket (fn [bracket-stack next-char]
                             (if (bracket-pairs next-char)
                               (conj bracket-stack next-char)
                               (let [last-open-bracket (peek bracket-stack)
                                     expected-close-bracket (bracket-pairs last-open-bracket)]
                                 (if (= next-char expected-close-bracket)
                                   (pop bracket-stack)
                                   (reduced next-char)))))
      part-1  (fn [bracket-stacks-or-illegal-characters]
                (->> bracket-stacks-or-illegal-characters
                     (filter char?)
                     (map {\) 3
                           \] 57
                           \} 1197
                           \> 25137})
                     (apply +)))

      part-2 (fn [bracket-stacks-or-illegal-characters]
               (->> bracket-stacks-or-illegal-characters
                    (filter vector?)
                    (map (fn [bracket-stack]
                           (->> bracket-stack
                                reverse
                                (map  {\( 1
                                       \[ 2
                                       \{ 3
                                       \< 4})
                                (reduce (fn [r n]
                                          (+ n  (* 5 r)))))))
                    sort
                    vec
                    (#(% (quot (count %) 2)))))]
  (->> lines
       (map (fn [line]
              (reduce consume-next-bracket [] line)))
       ((juxt part-1 part-2))))