-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path03.clj
81 lines (67 loc) · 2.63 KB
/
03.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(ns crossed-wires
(:require [clojure.string :as str]))
(def delta-ops {:R [:x +]
:L [:x -]
:U [:y +]
:D [:y -]})
(def other-coord {:x :y, :y :x})
(defn split-commas [s] (str/split s #","))
(defn segment-str->segment [segment-str]
{:dir (keyword (subs segment-str 0 1))
:delta (Integer/parseInt (subs segment-str 1))})
(def wires (->> (slurp "03.in")
str/split-lines
(mapv split-commas)))
(defn relative->absolute [segments]
(loop [pos {:x 0 :y 0}
segments segments
result {:h [], :v []}
sum 0]
(if-not (seq segments)
result
(let [segment (first segments)
[coord f] (delta-ops (:dir segment))
new-pos (merge-with f pos {coord (:delta segment)})
new-sum (+ sum (Math/abs (- (coord new-pos) (coord pos))))]
(recur new-pos
(rest segments)
(update result (coord {:x :h, :y :v})
#(conj % [(pos (other-coord coord)) (map coord [pos new-pos]) sum]))
new-sum)))))
(defn between? [from to n]
(let [[from to] (sort [from to])]
(and (<= from n to) n)))
(defn crosses?
[[fixed1 [from1 to1]]
[fixed2 [from2 to2]]]
(and (not= [0 0] [fixed1 fixed2])
(between? from1 to1 fixed2)
(between? from2 to2 fixed1)
{:x fixed2 :y fixed1}))
(defn overlaps?
[segment1 segment2]
(let [[fixed1 from-to1] segment1
[fixed2 from-to2] segment2
from-to1 (sort from-to1)
from-to2 (sort from-to2)
[before after] (sort-by first [from-to1 from-to2])]
(and (= fixed1 fixed2)
(<= (- (max (first from-to1) (first from-to2))
(min (second from-to1) (second from-to2))) 0))))
(def segments (mapv (fn [wire] (relative->absolute (mapv segment-str->segment wire)))
wires))
;;; part 1
(apply min (map (fn [{:keys [x y]}] (+ (Math/abs x) (Math/abs y)))
(let [[{hs1 :h vs1 :v} {hs2 :h vs2 :v}] segments
crossings (fn [hs vs] (for [h hs v vs :let [crosses (crosses? h v)] :when crosses]
crosses))]
(concat (crossings hs1 vs2) (crossings hs2 vs1)))))
;;; part 2
(defn crossings-delay [hs vs]
(for [[fixed1 [from1 to1] sum1 :as h] hs
[fixed2 [from2 to2] sum2 :as v] vs
:let [crosses (crosses? h v)] :when crosses]
(+ sum1 (Math/abs (- from1 fixed2))
sum2 (Math/abs (- from2 fixed1)))))
(apply min (let [[{hs1 :h vs1 :v} {hs2 :h vs2 :v}] segments]
(concat (crossings-delay hs1 vs2) (crossings-delay hs2 vs1))))