From a25122da57a575305839abac57f04cd7feb8fa1d Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Thu, 12 Dec 2019 15:57:17 -0800 Subject: [PATCH] Day 12: Part 2. --- src/12.rkt | 122 ++++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/src/12.rkt b/src/12.rkt index d007253..02b5b3a 100644 --- a/src/12.rkt +++ b/src/12.rkt @@ -4,24 +4,18 @@ "../lib.rkt") (define moons-pos - '((-9 -1 -1) - ( 2 9 5) - (10 18 -12) - (-6 15 -7))) + '((-9 -1 -1) ;; moon 1 + ( 2 9 5) ;; moon 2 + (10 18 -12) ;; moon 3 + (-6 15 -7))) ;; moon 4 +;; x y z (define moons-vel - '((0 0 0) - (0 0 0) - (0 0 0) - (0 0 0))) - -(define example - '((-1 0 2) - ( 2 -10 -7) - ( 4 -8 8) - ( 3 5 -1))) - -(define positions (mutable-set)) + '((0 0 0) ;; moon 1 + (0 0 0) ;; moon 2 + (0 0 0) ;; moon 3 + (0 0 0))) ;; moon 4 +;; vx vy vz (define (less-than->number n1 n2) (cond @@ -29,56 +23,68 @@ [(= n1 n2) 0] [(> n1 n2) -1])) -;; Calculate the velocity on the first moon -;; caused by the second moon -(define (velocity moon-on moon-by) - (list (less-than->number (first moon-on) (first moon-by)) - (less-than->number (second moon-on) (second moon-by)) - (less-than->number (third moon-on) (third moon-by)))) - -(define (<+> v1 v2) - (zip + v1 v2)) +;; velocity-1D : (listof pos) -> pos -> vel -> vel +;; Calculate the final velocity on the given moon +;; due to all other moons +(define (velocity-1D moons moon vel) + (+ vel (sum (map (∂ less-than->number moon) moons)))) +;; velocities-1D : (listof pos) -> (listof vel) -> (listof vel) ;; Calculate velocities for all moons -(define (velocities moons vels) - (zip <+> vels - (map (λ (moon) - (foldl (λ (other v) - (<+> v (velocity moon other))) - '(0 0 0) moons)) - moons))) +(define (velocities-1D moons vels) + (map (∂ velocity-1D moons) moons vels)) +;; step-1D : (listof pos) -> (listof vel) -> (values (listof pos) (listof vel)) +;; Step moon trajectories once +(define (step-1D moons vels) + (let* ([vels (velocities-1D moons vels)] + [moons (zip + moons vels)]) + (values moons vels))) + +;; step-n-1D : number -> (listof pos) -> (listof vel) -> (values (listof pos) (listof vel)) +;; Step moon trajectories n times +(define (step-n-1D n moons vels) + (if (zero? n) + (values moons vels) + (let-values ([(moons vels) (step-1D moons vels)]) + (step-n-1D (sub1 n) moons vels)))) + +;; loop-steps-1D : (listof pos) -> (listof vel) -> number +;; Calculate steps to loop back to original position +(define (loop-steps-1D moons* vels*) + (let loop ([steps 1] + [moons moons*] + [vels vels*]) + (if (and (> steps 1) (equal? moons moons*)) + steps + (let*-values ([(moons* vels*) + (step-1D moons vels)]) + (loop (add1 steps) moons* vels*))))) + +;; energy : (listof (list xpos ypos zpos)) -> (listof (list xvel yvel zvel)) -> number +;; Calculate total energy (in three dimensions) (define (energy moons vels) - (sum (zip (λ (moon vel) + (sum (map (λ (moon vel) (* (sum (map abs moon)) (sum (map abs vel)))) moons vels))) -(define (step moons vels) - (let* ([vels (velocities moons vels)] - [moons (zip <+> moons vels)]) - (values moons vels))) - -(define (step-n n moons vels) - (if (zero? n) - (values moons vels) - (let-values ([(moons vels) (step moons vels)]) - (step-n (sub1 n) moons vels)))) - (define part1 - (let-values ([(moons vels) - (step-n 1000 moons-pos moons-vel)]) - (energy moons vels))) + (let* ([moons (transpose moons-pos)] ;; moons : (list (listof xpos) (listof ypos) (listof zpos)) + [vels (transpose moons-vel)]) ;; vels : (list (listof xvel) (listof yvel) (listof zvel)) + (let*-values ([(moons-x vels-x) (step-n-1D 1000 (first moons) (first vels))] + [(moons-y vels-y) (step-n-1D 1000 (second moons) (second vels))] + [(moons-z vels-z) (step-n-1D 1000 (third moons) (third vels))]) + (let ([moonsT (transpose (list moons-x moons-y moons-z))] + [velsT (transpose (list vels-x vels-y vels-z))]) + (energy moonsT velsT))))) -(define (part2-nogood) - (let loop ([steps 0] - [moons moons-pos] - [vels moons-vel]) - (if (set-member? positions moons) - steps - (let*-values ([(moons* vels*) - (step moons vels)]) - (set-add! positions moons) - (loop (add1 steps) moons* vels*))))) +(define part2 + (let* ([moons (transpose moons-pos)] ;; moons : (list (listof xpos) (listof ypos) (listof zpos)) + [vels (transpose moons-vel)] ;; vels : (list (listof xvel) (listof yvel) (listof zvel)) + [steps-x (loop-steps-1D (first moons) (first vels))] + [steps-y (loop-steps-1D (second moons) (second vels))] + [steps-z (loop-steps-1D (third moons) (third vels))]) + (lcm steps-x steps-y steps-z))) -(show-solution part1 #f) \ No newline at end of file +(show-solution part1 part2) \ No newline at end of file