87 lines
2.5 KiB
Racket
87 lines
2.5 KiB
Racket
#lang racket
|
|
|
|
(module+ test
|
|
(require rackunit))
|
|
|
|
(define (read-input filename)
|
|
(string->grid (file->string filename)))
|
|
|
|
(define (string->grid str)
|
|
(for/set ([line (string-split str)]
|
|
[i (in-naturals)]
|
|
#:when #t
|
|
[c (in-string line)]
|
|
[j (in-naturals)]
|
|
#:when (eq? c #\#))
|
|
(make-rectangular j i)))
|
|
|
|
(define (segment->direction x)
|
|
(define a (real-part x))
|
|
(define b (imag-part x))
|
|
(define r (gcd a b))
|
|
(make-rectangular (/ a r) (/ b r)))
|
|
|
|
(define (detected grid)
|
|
(for/hash ([x (in-set grid)])
|
|
(values x (for/set ([y (in-set grid)]
|
|
#:unless (= x y))
|
|
(segment->direction (- y x))))))
|
|
|
|
(define (find-station grid)
|
|
(define visible (detected grid))
|
|
(define max-visible (apply max (map set-count (hash-values visible))))
|
|
(define pos (for/first ([(k v) (in-hash visible)]
|
|
#:when (= max-visible (set-count v)))
|
|
k))
|
|
(values pos (hash-ref visible pos)))
|
|
|
|
(define (part1 filename)
|
|
(define grid (read-input filename))
|
|
(define-values (loc dirs) (find-station grid))
|
|
(set-count dirs))
|
|
|
|
(module+ test
|
|
(check-equal? (part1 "test") 8)
|
|
(check-equal? (part1 "input") 286))
|
|
|
|
(define (find-target grid station direction)
|
|
(define targets
|
|
(for/list ([x (in-set grid)]
|
|
#:unless (= x station)
|
|
#:when (real? (/ (- x station) direction))
|
|
#:when (<= 0 (/ (- x station) direction)))
|
|
x))
|
|
(car (sort targets
|
|
(λ (x y) (< (magnitude (- x station))
|
|
(magnitude (- y station)))))))
|
|
|
|
(define (rotate-left lst)
|
|
(if (empty? lst)
|
|
'()
|
|
(append (cdr lst) (list (car lst)))))
|
|
|
|
(define (rotate-right lst)
|
|
(reverse (rotate-left (reverse lst))))
|
|
|
|
(define (find-nth-target grid n)
|
|
(define-values (station directions) (find-station grid))
|
|
(define directions-sorted (rotate-right
|
|
(sort (set->list directions)
|
|
(λ (x y) (< (angle (* -i x)) (angle (* -i y)))))))
|
|
(define-values (final-grid targets)
|
|
(for/fold ([grid grid]
|
|
[targets '()])
|
|
([i (in-range n)]
|
|
[dir (in-cycle directions-sorted)])
|
|
(define target (find-target grid station dir))
|
|
(values (set-remove grid target)
|
|
(cons target targets))))
|
|
(car targets))
|
|
|
|
(define (part2 filename)
|
|
(define grid (read-input filename))
|
|
(define target (find-nth-target grid 200))
|
|
(+ (* 100 (real-part target)) (imag-part target)))
|
|
|
|
(module+ test
|
|
(check-equal? (part2 "input") 504))
|