diff --git a/src/day5.clj b/src/day5.clj new file mode 100644 index 0000000..af6bdaa --- /dev/null +++ b/src/day5.clj @@ -0,0 +1,101 @@ +(ns day5 + (:require [clojure.string :as string] + [helpers :refer [get-input]])) + +(def input-example +"47|53 +97|13 +97|61 +97|47 +75|29 +61|13 +75|53 +29|13 +97|29 +53|29 +61|53 +97|53 +61|29 +47|13 +75|47 +97|75 +47|61 +75|61 +47|29 +75|13 +53|13 + +75,47,61,53,29 +97,61,53,29,13 +75,29,13 +75,97,47,61,53 +61,13,29 +97,13,75,29,47") + +(def input + ;(string/split input-example #"\n\n") + (string/split (get-input 5) #"\n\n") + ) + +(def page-ordering-rules + (reduce + (fn [m el] + (let [[k v] (map parse-long (string/split el #"\|"))] + (if (get m k) + (update m k conj v) + (assoc m k [v])))) + {} + (string/split-lines (first input)))) + +(def page-updates + (let [parse-fn + (fn [l] + (->> + (string/split l #",") + (mapv parse-long)))] + (->> input second string/split-lines + (map parse-fn)))) + +(defn safe? [up] + (loop [up up seen #{}] + (if (empty? up) + true + (let [page (first up) + rule (get page-ordering-rules page)] + (if (some seen rule) + false + (recur (rest up) (conj seen page))))))) + +(def correctly-ordered-updates + (filter safe? page-updates)) + +(defn middle-page [up] + (get up (quot (count up) 2))) + +(println "Result:" (reduce + (map middle-page correctly-ordered-updates))) + +(defn breaking-page [up] + (loop [up up seen #{}] + (if (empty? up) + nil + (let [page (first up) + rule (get page-ordering-rules page) + broken (some seen rule)] + (if broken + [page broken] + (recur (rest up) (conj seen page))))))) + +(defn correct-order [up] + (if (safe? up) + (vec up) + (let [[wrong-page broken-rule] (breaking-page up) + [correct broken] (split-with (partial not= broken-rule) up) + [head tail] (split-with (partial not= wrong-page) broken)] + (correct-order + (concat correct (rest head) [wrong-page broken-rule] (rest tail)))))) + +(println "Result (part 2):" + (->> + (remove safe? page-updates) + (map (comp middle-page correct-order)) + (reduce +)))