|
| 1 | +(ns advent-of-clojure.2023.03 |
| 2 | + (:refer-clojure :exclude [symbol? test]) |
| 3 | + (:require |
| 4 | + [clojure.string :as str] |
| 5 | + [clojure.set :as set] |
| 6 | + [advent-of-clojure.util.matrix :as grid])) |
| 7 | + |
| 8 | +(def input (->> (-> "resources/2023/03.dat" slurp (str/split-lines)))) |
| 9 | + |
| 10 | +(def not-symbol (re-pattern #"[^\d\.]+")) |
| 11 | + |
| 12 | +(defn symbol? [s] |
| 13 | + (re-matches not-symbol (str s))) |
| 14 | + |
| 15 | +(defn digit-x [row y index number] |
| 16 | + (let [from (str/index-of row number index) |
| 17 | + to (+ from (count number))] |
| 18 | + (vec (for [x (range from to)] [y x])))) |
| 19 | + |
| 20 | +(defn digits [grid y] |
| 21 | + (let [row (get grid y)] |
| 22 | + (->> (re-seq #"\d+" row) |
| 23 | + (reduce |
| 24 | + (fn [{:keys [index] :as state} number] |
| 25 | + (let [digit (digit-x row y index number)] |
| 26 | + (-> state |
| 27 | + (assoc :index (-> digit last last inc)) |
| 28 | + (update :digits conj digit)))) |
| 29 | + {:digits [] :index 0}) |
| 30 | + :digits))) |
| 31 | + |
| 32 | +(defn adjecent-to-digits [bounds digits] |
| 33 | + (->> digits |
| 34 | + (mapcat (partial grid/diagonal-neighbours bounds)) |
| 35 | + (remove (set digits)))) |
| 36 | + |
| 37 | +(defn adjencent-symbol? [grid bounds points] |
| 38 | + (->> points |
| 39 | + (adjecent-to-digits bounds) |
| 40 | + (some #(symbol? (get-in grid %))))) |
| 41 | + |
| 42 | +(defn get-number [grid points] |
| 43 | + (->> points |
| 44 | + (map #(get-in grid %)) |
| 45 | + (apply str) |
| 46 | + parse-long)) |
| 47 | + |
| 48 | +(defn part-one [grid] |
| 49 | + (let [bounds (grid/bounds grid) |
| 50 | + digits (mapcat #(digits grid %) (range (count grid))) |
| 51 | + xf (comp |
| 52 | + (filter #(adjencent-symbol? grid bounds %)) |
| 53 | + (map #(get-number grid %)))] |
| 54 | + (transduce xf + digits))) |
| 55 | + |
| 56 | +(defn asterisks [grid y] |
| 57 | + (->> (get grid y) |
| 58 | + (map-indexed (fn [x c] (when (= c \*) [y x]))) |
| 59 | + (remove nil?))) |
| 60 | + |
| 61 | +(defn gear? [grid bounds digits asterisk] |
| 62 | + (let [neighbours (set (grid/diagonal-neighbours bounds asterisk)) |
| 63 | + adjecent-numbers (->> digits |
| 64 | + (filter #(seq (set/intersection neighbours (set %)))) |
| 65 | + (map #(get-number grid %)))] |
| 66 | + (when (= 2 (count adjecent-numbers)) |
| 67 | + adjecent-numbers))) |
| 68 | + |
| 69 | +(defn part-two [grid] |
| 70 | + (let [bounds (grid/bounds grid) |
| 71 | + rows (range (count grid)) |
| 72 | + asterisks (mapcat #(asterisks grid %) rows) |
| 73 | + digits (mapcat #(digits grid %) rows) |
| 74 | + xf (comp |
| 75 | + (keep #(gear? grid bounds digits %)) |
| 76 | + (map #(apply * %)))] |
| 77 | + (transduce xf + asterisks))) |
| 78 | + |
| 79 | +(comment |
| 80 | + (part-one input) |
| 81 | + (part-two input) |
| 82 | + ) |
0 commit comments