(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.math.numeric-tower :as math]]) ; -> [[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 [xs ys zs] (let [detect-dup (fn [[ct prev] state] (if (prev state) (reduced ct) [(inc ct) (conj prev state)])) dup-rep (partial reduce detect-dup [0 (hash-set)])] (reduce math/lcm (map dup-rep [xs ys zs])))) (defn day12 [] (let [input (mapv parse-coords (get-list-from-file (input-file))) input-x (mapv (fn [[[p _ _] [v _ _]]] [[p] [v]]) input) input-y (mapv (fn [[[_ p _] [_ v _]]] [[p] [v]]) input) input-z (mapv (fn [[[_ _ p] [_ _ v]]] [[p] [v]]) input) simulate (iterate step-simulation input) simulate-x (iterate step-simulation input-x) simulate-y (iterate step-simulation input-y) simulate-z (iterate step-simulation input-z)] (part1 (reduce + (map total-energy (nth simulate 1000)))) (part2 (find-cycle simulate-x simulate-y simulate-z))))