diff --git a/2023/src/day10.clj b/2023/src/day10.clj new file mode 100644 index 0000000..dce6a1d --- /dev/null +++ b/2023/src/day10.clj @@ -0,0 +1,125 @@ +(ns day10 + (:require + [clojure.math :as math] + [core :refer [get-puzzle-input]])) + +(def input (get-puzzle-input 10)) + +(def pipe-out-types {:left #{\- \7 \J \S} + :right #{\- \F \L \S} + :up #{\| \L \J \S} + :down #{\| \7 \F \S}}) + +(def char-map + (->> input + (map-indexed (fn [row line] + (map-indexed (fn [col c] + [[row col] c]) + line))) + (apply concat) + (into {}))) + +(def opposite-dir {:left :right + :right :left + :up :down + :down :up}) + +(def start (->> char-map + (filter #(= \S (second %))) + ffirst)) + +(defn follow-dir [loc dir] + (condp = dir + :up (update loc 0 dec) + :down (update loc 0 inc) + :left (update loc 1 dec) + :right (update loc 1 inc))) + +(def char-dir-map {\| [:up :down] + \- [:left :right] + \L [:right :up] + \F [:right :down] + \J [:left :up] + \7 [:left :down]}) + +(defn follow-pipe [loc from] + (let [c (char-map loc)] + (if (and (not (nil? c)) + (not= \. c)) + (let [dir (->> c + (char-dir-map) + (filter #(not= from %)) + (first)) + new-loc (follow-dir loc dir)] + (if ((pipe-out-types (opposite-dir dir)) (char-map new-loc)) + [new-loc dir] + nil)) + nil))) + +;; part 1 +(->> (for [start-dir [:up :down :left :right]] + (loop [loc (follow-dir start start-dir) + cnt 0 + from (opposite-dir start-dir) + visited #{}] + (if (or (= loc nil) (= loc start)) + cnt + (let [res (follow-pipe loc from)] + (if (or (= res nil) + (visited (first res))) + nil + (recur (first res) + (inc cnt) + (opposite-dir (second res)) + (conj visited loc))))))) + (filter (comp not nil?)) + (map #(/ % 2)) + (map math/round) + (into #{}) + (apply max)) + +;; part 2 +(let [path (->> (for [start-dir [:right :left :up :down]] + (loop [loc (follow-dir start start-dir) + route [] + from (opposite-dir start-dir) + visited #{}] + (if (or (= loc nil) (= loc start)) + route + (let [res (follow-pipe loc from)] + (if (or (= res nil) + (visited (first res))) + nil + (recur (first res) + (conj route loc) + (opposite-dir (second res)) + (conj visited loc))))))) + (filter (comp not nil?)) + (sort-by #(/ (count %) 2) >) + first + (into #{}) + (#(conj % start))) + by-row (->> path + (group-by first) + (map #(update % 1 (partial map second))) + (map #(update % 1 sort)) + (into {})) + by-col (->> path + (group-by second) + (map #(update % 1 (partial map first))) + (map #(update % 1 sort)) + (into {})) + coords (->> char-map + (map first) + (filter (comp not path)))] + (->> coords + (filter (fn [[row col]] + (or (->> row + by-row + (partition 2) + (some #(< (first %) col (second %)))) + (->> col + by-col + (partition 2) + (some #(< (first %) row (second %))))))) + count))