day19: more concise

master
Clyne 3 years ago
parent 4825944241
commit 8b3b4de57d

@ -1,26 +1,8 @@
(require '[clojure.core.reducers :as r]) (require '[clojure.core.reducers :as r])
(require 'clojure.string) (require 'clojure.string)
(defn build-scanner-reports (def orientation-vectors
"Splits slurped, split-lines'd input by scanner." [[[1 0 0] [0 1 0] [0 0 1]]
[input-lines]
(loop [scanners [] rem-input input-lines]
(if (empty? rem-input)
scanners
(let [[this nxt] (split-with (comp not empty?) rem-input)]
(recur
(->> (rest this)
(map #(read-string (clojure.string/join ["[" % "]"])))
(conj scanners))
(rest nxt))))))
(defn point-add [[a b c] [d e f]] [(+ a d) (+ b e) (+ c f)])
(defn orient [[x y z] [[a b c] [d e f] [g h i]]]
[(+ (* x a) (* y d) (* z g)) (+ (* x b) (* y e) (* z h)) (+ (* x c) (* y f) (* z i))])
(defn scanner-orientation [report or-index]
(let [or-vec [[[1 0 0] [0 1 0] [0 0 1]]
[[1 0 0] [0 0 -1] [0 1 0]] [[1 0 0] [0 0 -1] [0 1 0]]
[[1 0 0] [0 -1 0] [0 0 -1]] [[1 0 0] [0 -1 0] [0 0 -1]]
[[1 0 0] [0 0 1] [0 -1 0]] [[1 0 0] [0 0 1] [0 -1 0]]
@ -43,37 +25,32 @@
[[0 0 1] [0 1 0] [-1 0 0]] [[0 0 1] [0 1 0] [-1 0 0]]
[[0 -1 0] [0 0 1] [-1 0 0]] [[0 -1 0] [0 0 1] [-1 0 0]]
[[0 0 -1] [0 -1 0] [-1 0 0]] [[0 0 -1] [0 -1 0] [-1 0 0]]
[[0 1 0] [0 0 -1] [-1 0 0]]] [[0 1 0] [0 0 -1] [-1 0 0]]])
chosen (get or-vec or-index)]
(map #(orient (map - %) chosen) report))) (defn build-scanner-reports
"Splits slurped, split-line'd input by scanner."
[input-lines]
(loop [scanners [] rem-input input-lines]
(if (empty? rem-input)
scanners
(let [[this nxt] (split-with (comp not empty?) rem-input)]
(recur (->> (rest this)
(map #(read-string (clojure.string/join ["[" % "]"])))
(conj scanners))
(rest nxt))))))
(defn point-add [[a b c] [d e f]] [(+ a d) (+ b e) (+ c f)])
(defn orient [[x y z] [[a b c] [d e f] [g h i]]]
[(+ (* x a) (* y d) (* z g)) (+ (* x b) (* y e) (* z h)) (+ (* x c) (* y f) (* z i))])
(defn scanner-orientation [report or-index]
(map #(orient (map - %) (get orientation-vectors or-index)) report))
(defn scanner-orientations (defn scanner-orientations
"Builds list of scanner reports adjusted for all possible orientations." "Builds list of scanner reports adjusted for all possible orientations."
[report] [report]
(for [or-vec [[[1 0 0] [0 1 0] [0 0 1]] (for [or-vec orientation-vectors]
[[1 0 0] [0 0 -1] [0 1 0]]
[[1 0 0] [0 -1 0] [0 0 -1]]
[[1 0 0] [0 0 1] [0 -1 0]]
[[-1 0 0] [0 -1 0] [0 0 1]]
[[-1 0 0] [0 0 -1] [0 -1 0]]
[[-1 0 0] [0 1 0] [0 0 -1]]
[[-1 0 0] [0 0 1] [0 1 0]]
[[0 0 -1] [1 0 0] [0 -1 0]]
[[0 1 0] [1 0 0] [0 0 -1]]
[[0 0 1] [1 0 0] [0 1 0]]
[[0 -1 0] [1 0 0] [0 0 1]]
[[0 0 1] [-1 0 0] [0 -1 0]]
[[0 1 0] [-1 0 0] [0 0 1]]
[[0 0 -1] [-1 0 0] [0 1 0]]
[[0 -1 0] [-1 0 0] [0 0 -1]]
[[0 -1 0] [0 0 -1] [1 0 0]]
[[0 0 1] [0 -1 0] [1 0 0]]
[[0 1 0] [0 0 1] [1 0 0]]
[[0 0 -1] [0 1 0] [1 0 0]]
[[0 0 1] [0 1 0] [-1 0 0]]
[[0 -1 0] [0 0 1] [-1 0 0]]
[[0 0 -1] [0 -1 0] [-1 0 0]]
[[0 1 0] [0 0 -1] [-1 0 0]]]]
(map #(orient (map - %) or-vec) report))) (map #(orient (map - %) or-vec) report)))
(defn scanner-build-potential-links (defn scanner-build-potential-links
@ -88,68 +65,31 @@
(defn scanner-find-connection (defn scanner-find-connection
"Attempt to determine if s1 and s2 are linked through common beacons." "Attempt to determine if s1 and s2 are linked through common beacons."
[s1 s2] [s1 s2]
(let [potential-links (as-> (scanner-build-potential-links s1 s2) $ (loop [potential-links (as-> (scanner-build-potential-links s1 s2) $
(for [i (range 0 (count $))] [i (nth $ i)]))] (for [i (range 0 (count $))] [i (nth $ i)])
(filter some? (into [] $))]
(map (when-let [[orientation link] (first potential-links)]
(fn [[orientation link]] (if-let [match (first (drop-while #(< (val %) 12) (frequencies (reduce concat link))))]
(let [distinct-points (into [] (distinct (reduce concat link))) [orientation (key match)]
link-results (recur (rest potential-links))))))
(into '()
(r/fold (quot (count distinct-points) 16) r/cat
(fn [pcoll point]
(if-not (empty? pcoll)
pcoll
(let [occurrance-count (reduce
#(cond-> %1
(not (empty? (filter (partial = point) %2)))
inc)
1 link)]
(cond-> pcoll (> occurrance-count 11) (r/append! point)))))
distinct-points))]
(when (not (empty? link-results))
[orientation (first link-results)])))
(into [] potential-links)))))
(defn scanner-merge (defn scanner-merge
"Merges the report of linked scanner s2 into scanner s1." "Merges the report of linked scanner s2 into scanner s1."
[s1 s2 s2-or s2-coord] [s1 s2 s2-or s2-coord]
(let [s2-ored (scanner-orientation s2 s2-or)] (vec (into (set s1) (map #(point-add s2-coord (map - %)) (scanner-orientation s2 s2-or)))))
(distinct (concat s1 (map #(point-add s2-coord (map - %)) s2-ored)))))
(def reports (->> (slurp "./in")
(clojure.string/split-lines)
(build-scanner-reports)
(vec)))
(let [[beacon-count scanner-coords] (let [[beacon-count scanner-coords]
(loop [new-reps reports sc-coords '([0 0 0]) i (range 1 (count reports))] (loop [new-reps (->> (slurp "./in") clojure.string/split-lines build-scanner-reports)
(println "Trying" (first i) (map count new-reps)) sc-coords '([0 0 0])
(if (nil? (first i)) next-reps (rest new-reps)]
; reached end (uh oh?) (if-let [next-rep (first next-reps)]
[(count new-reps) sc-coords] (if-let [[found-or found-coord] (scanner-find-connection (first new-reps) next-rep)]
; scan for links to report i (let [new-base (scanner-merge (first new-reps) next-rep found-or found-coord)
(let [found (scanner-find-connection (first new-reps) newest-reps (->> (assoc new-reps 0 new-base) (filterv (partial not= next-rep)))]
(get new-reps (first i)))] (println "found" found-coord)
(if (empty? found) (recur newest-reps (conj sc-coords found-coord) (rest newest-reps)))
; no match, move to next i (recur new-reps sc-coords (rest next-reps)))
(recur new-reps sc-coords (rest i)) [(count (first new-reps)) sc-coords]))]
(do (println " Found" found)
(recur
(-> new-reps
; replace index zero with merged report
(assoc 0 (scanner-merge (first new-reps)
(get new-reps (first i))
(first (first found))
(second (first found))))
; remove report we pulled from
(#(concat (subvec % 0 (first i))
(subvec % (inc (first i)))))
; back to vector
(vec))
(conj sc-coords (second (first found)))
; begin new scan
(range 1 (count new-reps))))))))]
(println "Part 1:" beacon-count) (println "Part 1:" beacon-count)
(println "Part 2:" (println "Part 2:"
(apply max (apply max

Loading…
Cancel
Save