-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday19.clj
94 lines (82 loc) · 2.92 KB
/
day19.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
82
83
84
85
86
87
88
89
90
91
92
93
94
(ns org.vuxu.aoc2021.day19
(:require [clojure.string :as str]
[clojure.set :as set]))
(def data
(for [scanner (str/split (slurp "day19") #"\n\n")]
(->> (str/split-lines scanner)
(drop 1)
(map #(str/split % #","))
(mapv (partial mapv parse-long)))))
(def axes [[0 1 0] [0 -1 0] [1 0 0] [-1 0 0] [0 0 1] [0 0 -1]])
(defn transform [[x y z] up rot]
(let [[rx ry rz] (case up
[ 0 1 0] [x y z]
[ 0 -1 0] [x (- y) (- z)]
[ 1 0 0] [y x (- z)]
[-1 0 0] [y (- x) z]
[ 0 0 1] [y z x]
[ 0 0 -1] [y (- z) (- x)])]
(case rot
0 [rx ry rz]
1 [rz ry (- rx)]
2 [(- rx) ry (- rz)]
3 [(- rz) ry rx])))
(defn translate [p v]
(mapv + p v))
(defn diff [v1 v2]
(mapv - v1 v2))
(defn align [beacons1 beacons2]
(first
(for [axis axes
rotation (range 4)
:let [rotated-beacons2 (map #(transform % axis rotation) beacons2)]
b1 beacons1
matching-b1-in-b2 rotated-beacons2
:let [delta (diff b1 matching-b1-in-b2)
transformed-beacons2 (set (map #(translate % delta) rotated-beacons2))
intersection (set/intersection transformed-beacons2 beacons1)]
:when (>= (count intersection) 12)]
[transformed-beacons2 delta axis rotation])))
(defn reduc [scans scanners]
(let [[to-remove scans scanners]
(loop [to-remove #{}
scans scans
scanners scanners
i 0
j 1]
(prn [i j])
(if (>= i (dec (count scans)))
[to-remove scans scanners]
(if (>= j (count scans))
(recur to-remove scans scanners (inc i) (+ i 2))
(if (to-remove j)
(recur to-remove scans scanners i (inc j))
(if-let [[agt trs up rot] (align (scans i) (scans j))]
(recur (conj to-remove j)
(update scans i set/union agt)
(update scanners i set/union
(set (map #(translate trs (transform % up rot)) (scanners j))))
i
(inc j))
(recur to-remove scans scanners i (inc j)))))))]
[(vec (keep-indexed #(when (not (to-remove %1)) %2) scans))
(vec (keep-indexed #(when (not (to-remove %1)) %2) scanners))]))
;; very slow :/
(def reducd
(loop [[scans scanners]
[(mapv set data) (mapv (constantly #{[0 0 0]}) data)]]
(if (> (count scans) 1)
(recur (reduc scans scanners))
[(first scans)
(first scanners)])))
(def part1
(count (first reducd)))
;; => 445
(defn manhattan [a b]
(apply + (map #(Math/abs %) (diff a b))))
(def part2
(apply max
(for [b1 (second reducd)
b2 (second reducd)]
(manhattan b1 b2))))
;; => 13225