Skip to content

Instantly share code, notes, and snippets.

@sotolf2
Last active December 12, 2019 11:45
Show Gist options
  • Save sotolf2/b3ead8a6a4f28b1ceabb928a8e2d27ab to your computer and use it in GitHub Desktop.
Save sotolf2/b3ead8a6a4f28b1ceabb928a8e2d27ab to your computer and use it in GitHub Desktop.
#lang racket
(require threading)
(require racket/set)
(struct point (x y z) #:transparent)
(struct velocity (x y z) #:transparent)
(struct moon (position velocity) #:transparent)
(define (get-input)
(file->lines "day12.txt"))
(define (get-test)
(file->lines "day12-test.txt"))
(define (parse points)
(define (parse-line point-string)
(~> point-string
(string-replace "<" "")
(string-replace ">" "")
(string-split ",")
(map (λ (part) (string->number (cadr (string-split part "=")))) _)
(apply point _)
(moon (velocity 0 0 0))))
(map parse-line points))
(define (velocity-add a b)
(velocity (+ (velocity-x a) (velocity-x b))
(+ (velocity-y a) (velocity-y b))
(+ (velocity-z a) (velocity-z b))))
(define (velocity-add-deltas a deltas)
(foldl velocity-add a deltas))
(define (positions->velocity-change a b)
(define (delta->change delta)
(cond [(zero? delta) 0]
[(negative? delta) 1]
[(positive? delta) -1]))
(let* ([dx (- (point-x a) (point-x b))]
[dy (- (point-y a) (point-y b))]
[dz (- (point-z a) (point-z b))])
(velocity (delta->change dx) (delta->change dy) (delta->change dz))))
(define (get-new-velocity mn mns)
(~>> mns
(map (λ (x) (positions->velocity-change (moon-position mn) (moon-position x))))
(velocity-add-deltas (moon-velocity mn))))
(define (update-velocities mns)
(define (loop mns all res)
(if (empty? mns)
(reverse res)
(loop
(cdr mns)
all
(cons (moon (moon-position (car mns)) (get-new-velocity (car mns) all)) res))))
(loop mns mns '()))
(define (apply-velocity mn)
(let ([pos (moon-position mn)]
[vel (moon-velocity mn)])
(moon
(point
(+ (point-x pos) (velocity-x vel))
(+ (point-y pos) (velocity-y vel))
(+ (point-z pos) (velocity-z vel)))
vel)))
(define (apply-velocities mns)
(define (loop mns res)
(if (empty? mns)
(reverse res)
(loop
(cdr mns)
(cons (apply-velocity (car mns)) res))))
(loop mns '()))
(define (simulate-step mns)
(~> mns
(update-velocities)
(apply-velocities)))
(define (simulate-steps num mns)
(if (zero? num)
mns
(simulate-steps (- num 1) (simulate-step mns))))
(define (moon-energy mn)
(let ([pos (moon-position mn)]
[vel (moon-velocity mn)])
(*
(+ (abs (point-x pos)) (abs (point-y pos)) (abs (point-z pos)))
(+ (abs (velocity-x vel)) (abs (velocity-y vel)) (abs (velocity-z vel))))))
(define (system-energy mns)
(~>> mns
(map moon-energy)
(apply +)))
(define (part1)
(~>>
(get-input)
(parse)
(simulate-steps 1000)
(system-energy)))
(define (point-by dim)
(cond [(equal? 'x dim) point-x]
[(equal? 'y dim) point-y]
[(equal? 'z dim) point-z]))
(define (velocity-by dim)
(cond [(equal? 'x dim) velocity-x]
[(equal? 'y dim) velocity-y]
[(equal? 'z dim) velocity-z]))
(define (moon-dim-equal? dim a b)
(let ([apx ((point-by dim) (moon-position a))]
[bpx ((point-by dim) (moon-position b))]
[avx ((velocity-by dim) (moon-velocity a))]
[bvx ((velocity-by dim) (moon-velocity b))])
(and (= apx bpx) (= avx bvx))))
(define (system-equal-by cmpf a b)
(andmap cmpf a b))
(define (find-repeating cmp mns)
(define (loop mns init steps)
(if (system-equal-by cmp mns init)
steps
(loop
(simulate-step mns)
init
(+ 1 steps))))
(loop (simulate-step mns) mns 1))
(define (part2)
(let ([mns (parse (get-input))])
(lcm (find-repeating (curry moon-dim-equal? 'x) mns) (find-repeating (curry moon-dim-equal? 'y) mns) (find-repeating (curry moon-dim-equal? 'z) mns))))
(part1)
(part2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment