f4f8705ccf34

2019/12
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Thu, 12 Dec 2019 20:02:09 -0500
parents ebd2a1bb4889
children 491cb9e15096
branches/tags (none)
files data/2019/12.txt src/2019/days/day-12.lisp

Changes

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/2019/12.txt	Thu Dec 12 20:02:09 2019 -0500
@@ -0,0 +1,4 @@
+<x=3, y=2, z=-6>
+<x=-13, y=18, z=10>
+<x=-8, y=-1, z=13>
+<x=5, y=10, z=4>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/2019/days/day-12.lisp	Thu Dec 12 20:02:09 2019 -0500
@@ -0,0 +1,77 @@
+(defpackage :advent/2019/12 #.cl-user::*advent-use*)
+(in-package :advent/2019/12)
+
+(defclass* moon () (pos vel))
+
+(defun make-moon (x y z)
+  (make-instance 'moon
+    :pos (vector x y z)
+    :vel (vector 0 0 0)))
+
+(defun parse-moons (data)
+  (mapcar (curry #'apply #'make-moon) data))
+
+(defun apply-gravity (moon other)
+  (map-into (vel moon) (lambda (v m o)
+                         (+ v (signum (- o m))))
+            (vel moon)
+            (pos moon)
+            (pos other)))
+
+(defun apply-all-gravity (moons)
+  (alexandria:map-permutations (curry #'apply #'apply-gravity)
+                               moons :length 2 :copy nil))
+
+(defun vincf (vec delta)
+  (map-into vec #'+ vec delta))
+
+(defun apply-velocity (moon)
+  (vincf (pos moon) (vel moon)))
+
+(defun apply-all-velocity (moons)
+  (map nil #'apply-velocity moons))
+
+(defun tick (moons &optional (n 1))
+  (do-repeat n
+    (apply-all-gravity moons)
+    (apply-all-velocity moons)))
+
+(defmethod energy ((moon moon))
+  (* (summation (pos moon) :key #'abs)
+     (summation (vel moon) :key #'abs)))
+
+(defmethod energy ((moons sequence))
+  (summation moons :key #'energy))
+
+(defun velocity-zeroed-p (moons axis)
+  (iterate (for moon :in moons)
+           (always (zerop (aref (vel moon) axis)))))
+
+(defun part2 (moons)
+  ;; Clever trick from https://www.reddit.com/r/adventofcode/comments/e9nqpq/day_12_part_2_2x_faster_solution/
+  (iterate
+    (for tick :from 1)
+    (tick moons)
+    (finding-first tick :such-that (velocity-zeroed-p moons 0) :into x)
+    (finding-first tick :such-that (velocity-zeroed-p moons 1) :into y)
+    (finding-first tick :such-that (velocity-zeroed-p moons 2) :into z)
+    (until (and x y z))
+    (returning (* 2 (lcm x y z)))))
+
+(define-problem (2019 12) (data read-lines-of-numbers-and-garbage) (14780 279751820342592)
+  (values
+    (let ((moons (parse-moons data)))
+      (tick moons 1000)
+      (energy moons))
+    (part2 (parse-moons data))))
+
+
+#; Scratch --------------------------------------------------------------------
+
+(defparameter *a* (make-moon '(0 0 0)))
+(defparameter *b* (make-moon '(1 0 -2)))
+
+(run '((-1  0  2)
+       (2  -10  -7)
+       (4  -8  8)
+       (3  5  -1)))