(ns adventofcode2019.day12 [:require [adventofcode2019.lib :refer :all] [adventofcode2019.intcode :as i] [clojure.string :as str] [clojure.core.match :refer [match]] [clojure.math.combinatorics :as combo] [clojure.pprint :refer [pprint]]]) ; -> [[1 2 3] [0 0 0]] (defn parse-coords [coords] [(mapv parse-int (str/split (str/replace coords #"[<>xyz=,]" "") #" ")) [0 0 0]]) (defn gravity [[pos1 vel1] [pos2 vel2]] (let [adjust-velocity (fn [a b] (cond (< a b) [inc dec] (= a b) [identity identity] (> a b) [dec inc])) velocity-diffs (map adjust-velocity pos1 pos2) apply-diffs (fn [acc vel] (mapv #(%1 %2) (map acc velocity-diffs) vel))] [(apply-diffs first vel1) (apply-diffs second vel2)])) (defn velocity [[pos vel]] [(mapv + pos vel) vel]) (defn total-energy [[pos vel]] (let [abs+ (fn [& args] (apply + (map #(Math/abs %) args))) potential (apply abs+ pos) kinetic (apply abs+ vel)] (* potential kinetic))) (defn step-simulation [bodies] (let [indices (range (count bodies)) all-pairs (combo/combinations indices 2) apply-gravity (fn [bodies [i j]] (let [[nv1 nv2] (gravity (bodies i) (bodies j))] (-> bodies (assoc-in [i 1] nv1) (assoc-in [j 1] nv2))))] (mapv velocity (reduce apply-gravity bodies all-pairs)))) (defn find-cycle [states] (let [detect-dup (fn [[ct prev] state] (if (= (flatten prev) (map - (flatten state))) (reduced (inc ct)) [(inc ct) state]))] (* 2 (reduce detect-dup [0 []] states)))) (defn day12 [] (let [input (mapv parse-coords (get-list-from-file (input-file))) simulate (iterate step-simulation input)] (part1 (reduce + (map total-energy (nth simulate 1000)))) (part2 (find-cycle simulate))))