90 lines
3.1 KiB
Racket
90 lines
3.1 KiB
Racket
#lang racket
|
|
|
|
(require racket/set
|
|
"../lib.rkt")
|
|
|
|
(define moons-pos
|
|
'((-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) ;; 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
|
|
[(< n1 n2) 1]
|
|
[(= n1 n2) 0]
|
|
[(> n1 n2) -1]))
|
|
|
|
;; 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-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 (map + 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 (map (λ (moon vel)
|
|
(* (sum (map abs moon))
|
|
(sum (map abs vel))))
|
|
moons vels)))
|
|
|
|
(define part1
|
|
(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
|
|
(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 part2) |