1
0
Fork 0

Day 12: Part 2.

This commit is contained in:
Jonathan Chan 2019-12-12 15:57:17 -08:00
parent 23d605ab45
commit 3ce83e7f43
1 changed files with 64 additions and 58 deletions

View File

@ -4,24 +4,18 @@
"../lib.rkt") "../lib.rkt")
(define moons-pos (define moons-pos
'((-9 -1 -1) '((-9 -1 -1) ;; moon 1
( 2 9 5) ( 2 9 5) ;; moon 2
(10 18 -12) (10 18 -12) ;; moon 3
(-6 15 -7))) (-6 15 -7))) ;; moon 4
;; x y z
(define moons-vel (define moons-vel
'((0 0 0) '((0 0 0) ;; moon 1
(0 0 0) (0 0 0) ;; moon 2
(0 0 0) (0 0 0) ;; moon 3
(0 0 0))) (0 0 0))) ;; moon 4
;; vx vy vz
(define example
'((-1 0 2)
( 2 -10 -7)
( 4 -8 8)
( 3 5 -1)))
(define positions (mutable-set))
(define (less-than->number n1 n2) (define (less-than->number n1 n2)
(cond (cond
@ -29,56 +23,68 @@
[(= n1 n2) 0] [(= n1 n2) 0]
[(> n1 n2) -1])) [(> n1 n2) -1]))
;; Calculate the velocity on the first moon ;; velocity-1D : (listof pos) -> pos -> vel -> vel
;; caused by the second moon ;; Calculate the final velocity on the given moon
(define (velocity moon-on moon-by) ;; due to all other moons
(list (less-than->number (first moon-on) (first moon-by)) (define (velocity-1D moons moon vel)
(less-than->number (second moon-on) (second moon-by)) (+ vel (sum (map ( less-than->number moon) moons))))
(less-than->number (third moon-on) (third moon-by))))
(define (<+> v1 v2)
(zip + v1 v2))
;; velocities-1D : (listof pos) -> (listof vel) -> (listof vel)
;; Calculate velocities for all moons ;; Calculate velocities for all moons
(define (velocities moons vels) (define (velocities-1D moons vels)
(zip <+> vels (map ( velocity-1D moons) moons vels))
(map (λ (moon)
(foldl (λ (other v)
(<+> v (velocity moon other)))
'(0 0 0) moons))
moons)))
;; 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) (define (energy moons vels)
(sum (zip (λ (moon vel) (sum (map (λ (moon vel)
(* (sum (map abs moon)) (* (sum (map abs moon))
(sum (map abs vel)))) (sum (map abs vel))))
moons vels))) 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 (define part1
(let-values ([(moons vels) (let* ([moons (transpose moons-pos)] ;; moons : (list (listof xpos) (listof ypos) (listof zpos))
(step-n 1000 moons-pos moons-vel)]) [vels (transpose moons-vel)]) ;; vels : (list (listof xvel) (listof yvel) (listof zvel))
(energy moons vels))) (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) (define part2
(let loop ([steps 0] (let* ([moons (transpose moons-pos)] ;; moons : (list (listof xpos) (listof ypos) (listof zpos))
[moons moons-pos] [vels (transpose moons-vel)] ;; vels : (list (listof xvel) (listof yvel) (listof zvel))
[vels moons-vel]) [steps-x (loop-steps-1D (first moons) (first vels))]
(if (set-member? positions moons) [steps-y (loop-steps-1D (second moons) (second vels))]
steps [steps-z (loop-steps-1D (third moons) (third vels))])
(let*-values ([(moons* vels*) (lcm steps-x steps-y steps-z)))
(step moons vels)])
(set-add! positions moons)
(loop (add1 steps) moons* vels*)))))
(show-solution part1 #f) (show-solution part1 part2)