f4f8705ccf34
2019/12
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)))