Brute force brute force...
This commit is contained in:
parent
619cafeecc
commit
4580ab6256
|
@ -0,0 +1,81 @@
|
|||
#lang racket
|
||||
|
||||
(define (parse-input inp)
|
||||
(string-split (string-trim inp)))
|
||||
|
||||
(define input (parse-input (file->string "input.10.txt")))
|
||||
(define size (max (length input) (string-length (first input))))
|
||||
|
||||
(struct pos [x y] #:transparent)
|
||||
|
||||
(define (input->positions inp)
|
||||
(apply append
|
||||
(for/list ([line inp] [y (in-range (length inp))])
|
||||
(for/list ([char line] [x (in-range (string-length line))] #:when (equal? char #\#))
|
||||
(pos x y)))))
|
||||
|
||||
(define asteroids (apply set (input->positions input)))
|
||||
|
||||
(define (pos-on-line a b c)
|
||||
(define (pos-on-line+ a b c)
|
||||
(let ([crs (- (* (- (pos-y c) (pos-y a)) (- (pos-x b) (pos-x a)))
|
||||
(* (- (pos-x c) (pos-x a)) (- (pos-y b) (pos-y a))))]
|
||||
[dot (+ (* (- (pos-x c) (pos-x a)) (- (pos-x b) (pos-x a)))
|
||||
(* (- (pos-y c) (pos-y a)) (- (pos-y b) (pos-y a))))]
|
||||
[sqdist (+ (sqr (- (pos-x b) (pos-x a)))
|
||||
(sqr (- (pos-y b) (pos-y a))))])
|
||||
(cond [(not (zero? crs)) #f]
|
||||
[(negative? dot) #f]
|
||||
[(<= dot sqdist)])))
|
||||
(or (equal? b c) (pos-on-line+ a b c) (pos-on-line+ a c b)))
|
||||
|
||||
(define (collide-line-pos start to pos-set)
|
||||
(for/set ([pos pos-set] #:when (pos-on-line start to pos))
|
||||
pos))
|
||||
|
||||
(define (count-reachable-asteroids pos-set start)
|
||||
(define pos-set/nostart (set-remove pos-set start))
|
||||
(define (count-reachable+ pos-set start)
|
||||
(cond [(set-empty? pos-set) 0]
|
||||
[else (begin
|
||||
(define any (set-first pos-set))
|
||||
(define reachables (collide-line-pos start any pos-set))
|
||||
(add1 (count-reachable+ (set-subtract pos-set reachables) start)))]))
|
||||
(count-reachable+ pos-set/nostart start))
|
||||
|
||||
;; Part 1
|
||||
;; The super naive way lol
|
||||
(define best (argmax (curry count-reachable-asteroids asteroids) (set->list asteroids)))
|
||||
(count-reachable-asteroids asteroids best)
|
||||
|
||||
(define (dist-between p1 p2)
|
||||
(sqrt (+ (sqr (- (pos-x p1) (pos-x p2))) (sqr (- (pos-y p1) (pos-y p2))))))
|
||||
|
||||
;; intentionally flip y and x for fun and profit
|
||||
;; also negative x
|
||||
;; (this is fuckery to get the sweep to start at 0 and go the normal direction)
|
||||
(define (angle-to center p)
|
||||
(define dx (- (pos-x center) (pos-x p)))
|
||||
(define dy (- (pos-y p) (pos-y center)))
|
||||
(+ (* 2 pi) (atan dx dy)))
|
||||
|
||||
(define sorted (sort (set->list (set-remove asteroids best)) < #:key (curry angle-to best)))
|
||||
(define grouped (group-by (curry angle-to best) sorted))
|
||||
|
||||
(define (min-of-group group)
|
||||
(argmin (curry dist-between best) group))
|
||||
|
||||
(define (destroy-asteroids grouped n)
|
||||
(cond [(zero? n) (min-of-group (first grouped))]
|
||||
[else
|
||||
(let* ([this-group (first grouped)]
|
||||
[min-asteroid (min-of-group this-group)]
|
||||
[rest-of-group (remove min-asteroid this-group)])
|
||||
(cond [(empty? rest-of-group) (destroy-asteroids (rest grouped) (sub1 n))]
|
||||
[else (destroy-asteroids
|
||||
(append (rest grouped) (list rest-of-group)) (sub1 n))]))]))
|
||||
|
||||
;; I am like
|
||||
;; 200 billion % not sure why this is 198 and not 199 (ie, 200 but starting at zero)
|
||||
;; but it rly do be like that sometime
|
||||
(destroy-asteroids grouped 198)
|
Loading…
Reference in New Issue