1
0
Fork 0
adventofcode/src/12.rkt

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)