(ns adventofcode2019.day03 [:require [adventofcode2019.lib :refer :all] [clojure.string :as str] [clojure.set :as set] [clojure.math.combinatorics :as combo]]) (defn parse-input [input] (map #(str/split % #",") (str/split-lines (str/trim (slurp input))))) (defn spec->op [spec] (let [direction (first spec) distance (parse-int (str/join (rest spec)))] (case direction \U (fn [[x y]] [x (+ y distance)]) \D (fn [[x y]] [x (- y distance)]) \R (fn [[x y]] [(+ x distance) y]) \L (fn [[x y]] [(- x distance) y])))) (defn ints-between [x y] (cond (> x y) (reverse (range y (inc x))) (< x y) (range x (inc y)) :else [x])) (defn points-diff [pos-a pos-b] (let [[a-x a-y] pos-a [b-x b-y] pos-b] (rest (for [x (ints-between a-x b-x) y (ints-between a-y b-y)] [x y])))) (defn wire-spec->points [wire] (let [wire-ops (map spec->op wire) trace-reduction (fn [{:keys [pos points]} op] (let [new-pos (op pos) new-points (points-diff pos new-pos)] {:pos new-pos :points (concat points new-points)})) trace (reduce trace-reduction {:pos [0 0], :points []} wire-ops)] (:points trace))) (defn find-intersections [wires] (let [wires-points (map wire-spec->points wires) intersections (apply set/intersection (map set wires-points)) find-steps (fn [i pos] (when (intersections pos) {pos (inc i)})) step-counts (map #(map-indexed find-steps %) wires-points)] (apply (partial merge-with +) (flatten step-counts)))) (defn day03 [] (let [wires (parse-input (input-file)) manhattan-distance (fn [[x y]] (+ (Math/abs x) (Math/abs y))) intersections (find-intersections wires)] (println (apply min (map manhattan-distance (keys intersections)))) (println (apply min (vals intersections)))))