--- /dev/null
+(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]]])
+
+; <x=1, y=2, z=3> -> [[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 day12 []
+ (let [input (map parse-coords (get-list-from-file (input-file)))
+ simulate (iterate step-simulation input)]
+ (part1 (reduce + (map total-energy (nth simulate 1000))))
+ #_(part2)))