| 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)))) |