aoc2019/12.rkt

68 lines
2.2 KiB
Racket

#lang racket
(struct vec [x y z] #:transparent)
(define (vec->list v) (list (vec-x v) (vec-y v) (vec-z v)))
(define (vec+ . vecs)
(define x (apply + (map vec-x vecs)))
(define y (apply + (map vec-y vecs)))
(define z (apply + (map vec-z vecs)))
(vec x y z))
(define lines (string-split (string-trim (file->string "input.12.txt")) "\n"))
(define (parse-line line)
(map string->number (regexp-match* #rx"[0-9\\-]+" line)))
(define input (map (compose (curry apply vec) parse-line) lines))
(define (bound val)
(cond [(negative? val) -1]
[(positive? val) 1]
[else 0]))
(define (gravity-axis val1 val2)
(bound (- val2 val1)))
(define (gravity-axis-all lop pos)
(apply + (map (curry gravity-axis pos) lop)))
(define (gravity pos1 pos2)
(apply vec (map gravity-axis (vec->list pos1) (vec->list pos2))))
(define (gravity-all lop pos)
(apply vec+ (map (curry gravity pos) lop)))
(define (initial-vels lop)
(map (lambda (x) (vec 0 0 0)) lop))
(define (sim-step lop [lov (initial-vels lop)])
(define loa (map (curry gravity-all lop) lop))
(define new-lov (map vec+ lov loa))
(define new-lop (map vec+ lop new-lov))
(list new-lop new-lov))
(define (energy v)
(apply + (map abs (vec->list v))))
(define final-state (for/foldr ([state (list input (initial-vels input))])
([i (in-range 1000)])
(apply sim-step state)))
;; Functional heckcode time
;; (Sorry lol)
(apply + (apply map * (map (curry map energy) final-state)))
(define (sim-step-axis lop [lov (map (lambda (x) 0) lop)])
(define loa (map (curry gravity-axis-all lop) lop))
(define new-lov (map + lov loa))
(define new-lop (map + lop new-lov))
(list new-lop new-lov))
(define (find-repeat-axis initial-lop [lop initial-lop] [lov (map (lambda (x) 0) lop)] [acc 1])
(define next-state (sim-step-axis lop lov))
(cond
[(and (equal? initial-lop (first next-state)) (andmap zero? (second next-state))) acc]
[else (find-repeat-axis initial-lop (first next-state) (second next-state) (add1 acc))]))
(define repeat-x (find-repeat-axis (map vec-x input)))
(define repeat-y (find-repeat-axis (map vec-y input)))
(define repeat-z (find-repeat-axis (map vec-z input)))
(lcm repeat-x repeat-y repeat-z)