master
Matthew Butterick 5 years ago
parent 92ab44f92a
commit fa1327e70c

@ -8,7 +8,7 @@
(define (str->moons str) (define (str->moons str)
(for/list ([trip (in-slice 3 (parse-input str))]) (for/list ([trip (in-slice 3 (parse-input str))])
($moon trip (list 0 0 0)))) ($moon trip (list 0 0 0))))
(define (update-pair-velocity! m0 m1) (define (update-pair-velocity! m0 m1)
(define-values (new-m0-vel new-m1-vel) (define-values (new-m0-vel new-m1-vel)
@ -34,20 +34,20 @@
(unless (= 1 (length moons)) (unless (= 1 (length moons))
(match-define (cons m0 ms) moons) (match-define (cons m0 ms) moons)
(for ([m (in-list ms)]) (for ([m (in-list ms)])
(update-pair-velocity! m0 m)) (update-pair-velocity! m0 m))
(loop ms)))) (loop ms))))
(define (step! moons [count 1]) (define (step! moons [count 1])
(for ([i (in-range count)]) (for ([i (in-range count)])
(update-gravity! moons) (update-gravity! moons)
(for-each update-position! moons)) (for-each update-position! moons))
moons) moons)
(define (total-energy moons) (define (total-energy moons)
(for/sum ([moon (in-list moons)]) (for/sum ([moon (in-list moons)])
(apply * (for/list ([field-proc (list $moon-pos $moon-vel)]) (apply * (for/list ([field-proc (list $moon-pos $moon-vel)])
(for/sum ([val (in-list (field-proc moon))]) (for/sum ([val (in-list (field-proc moon))])
(abs val)))))) (abs val))))))
(check-eq? (check-eq?
(total-energy (step! (str->moons "<x=-1, y=0, z=2> (total-energy (step! (str->moons "<x=-1, y=0, z=2>
@ -69,36 +69,35 @@
9876) 9876)
;; 2 ;; 2
(define (shift-origin! moons pos)
(for ([moon (in-list moons)])
(set-$moon-pos! moon (map - ($moon-pos moon) pos))))
(define (period str) (define (period str)
(for*/list ([which-moon (list first second third fourth)] (apply lcm
[which-dim (list first second third)]) (for*/list ([dim (list first second third)])
(define moons (str->moons str)) (define moons (str->moons str))
(shift-origin! moons ($moon-pos (which-moon moons))) (define (get-dims) (for*/list ([moon (in-list moons)]
(let loop ([count 1]) [field (in-list (list $moon-pos $moon-vel))])
(step! moons) (dim (field moon))))
(if (and (= 0 (which-dim ($moon-pos (which-moon moons)))) (define dims0 (get-dims))
(= 0 (which-dim ($moon-vel (which-moon moons))))) (let loop ([count 0])
count (step! moons)
(loop (add1 count)))))) (if (andmap = dims0 (get-dims))
(add1 count)
(loop (add1 count)))))))
(check-eq? (check-eq?
(apply lcm (period "<x=-1, y=0, z=2> (period "<x=-1, y=0, z=2>
<x=2, y=-10, z=-7> <x=2, y=-10, z=-7>
<x=4, y=-8, z=8> <x=4, y=-8, z=8>
<x=3, y=5, z=-1>")) <x=3, y=5, z=-1>")
2772) 2772)
(check-eq? (check-eq?
(apply lcm (period "<x=-8, y=-10, z=0>
(period "<x=-8, y=-10, z=0>
<x=5, y=5, z=10> <x=5, y=5, z=10>
<x=2, y=-7, z=3> <x=2, y=-7, z=3>
<x=9, y=-8, z=-3>")) <x=9, y=-8, z=-3>")
4686774924) 4686774924)
(check-eq? (period (file->string "12.rktd")) 307043147758488)