]> localhost Git - adventofcode2019.git/blob - src/adventofcode2019/day12.clj
acf3ff60024e989c585f889d1442222d90d3e58b
[adventofcode2019.git] / src / adventofcode2019 / day12.clj
1 (ns adventofcode2019.day12
2 [:require [adventofcode2019.lib :refer :all]
3 [adventofcode2019.intcode :as i]
4 [clojure.string :as str]
5 [clojure.core.match :refer [match]]
6 [clojure.math.combinatorics :as combo]
7 [clojure.math.numeric-tower :as math]])
8
9 ; <x=1, y=2, z=3> -> [[1 2 3] [0 0 0]]
10 (defn parse-coords [coords]
11 [(mapv parse-int (str/split (str/replace coords #"[<>xyz=,]" "") #" "))
12 [0 0 0]])
13
14 (defn gravity [[pos1 vel1] [pos2 vel2]]
15 (let [adjust-velocity (fn [a b]
16 (cond
17 (< a b) [inc dec]
18 (= a b) [identity identity]
19 (> a b) [dec inc]))
20 velocity-diffs (map adjust-velocity pos1 pos2)
21 apply-diffs (fn [acc vel] (mapv #(%1 %2) (map acc velocity-diffs) vel))]
22 [(apply-diffs first vel1)
23 (apply-diffs second vel2)]))
24
25 (defn velocity [[pos vel]]
26 [(mapv + pos vel) vel])
27
28 (defn total-energy [[pos vel]]
29 (let [abs+ (fn [& args] (apply + (map #(Math/abs %) args)))
30 potential (apply abs+ pos)
31 kinetic (apply abs+ vel)]
32 (* potential kinetic)))
33
34 (defn step-simulation [bodies]
35 (let [indices (range (count bodies))
36 all-pairs (combo/combinations indices 2)
37 apply-gravity (fn [bodies [i j]]
38 (let [[nv1 nv2] (gravity (bodies i) (bodies j))]
39 (-> bodies
40 (assoc-in [i 1] nv1)
41 (assoc-in [j 1] nv2))))]
42 (mapv velocity (reduce apply-gravity bodies all-pairs))))
43
44 (defn find-cycle [xs ys zs]
45 (let [detect-dup (fn [[ct prev] state]
46 (if (prev state)
47 (reduced ct)
48 [(inc ct) (conj prev state)]))
49 dup-rep (partial reduce detect-dup [0 (hash-set)])]
50 (reduce math/lcm (map dup-rep [xs ys zs]))))
51
52 (defn day12 []
53 (let [input (mapv parse-coords (get-list-from-file (input-file)))
54 input-x (mapv (fn [[[p _ _] [v _ _]]] [[p] [v]]) input)
55 input-y (mapv (fn [[[_ p _] [_ v _]]] [[p] [v]]) input)
56 input-z (mapv (fn [[[_ _ p] [_ _ v]]] [[p] [v]]) input)
57 simulate (iterate step-simulation input)
58 simulate-x (iterate step-simulation input-x)
59 simulate-y (iterate step-simulation input-y)
60 simulate-z (iterate step-simulation input-z)]
61 (part1 (reduce + (map total-energy (nth simulate 1000))))
62 (part2 (find-cycle simulate-x simulate-y simulate-z))))