(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 axis-data (moons axis) (iterate (for moon :in moons) (collect (aref (pos moon) axis)) (collect (aref (vel moon) axis)))) (defun part2 (moons) (iterate (with tx = (axis-data moons 0)) (with ty = (axis-data moons 1)) (with tz = (axis-data moons 2)) (for tick :from 1) (tick moons) (finding-first tick :such-that (equal (axis-data moons 0) tx) :into x) (finding-first tick :such-that (equal (axis-data moons 1) ty) :into y) (finding-first tick :such-that (equal (axis-data moons 2) tz) :into z) (until (and x y z)) (returning (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)))