master
Matthew Butterick 5 years ago
parent de4018ffd5
commit 50e2a39a2a

@ -0,0 +1,6 @@
1, 1
1, 6
8, 3
3, 4
5, 5
8, 9

@ -0,0 +1,65 @@
#lang debug br
#|
Start with the area of the grid bounded by the locations.
Calculate the neighborhoods within this grid.
Any location that has a grid neighborhood that includes an edge piece
will grow to infinity (because adjacent pieces outside the grid will also be closest to that location)
So ignore those. And search the others for the answer.
|#
(define locs (for/list ([ln (in-lines (open-input-file "06.txt"))])
(match (map string->number (string-split ln ", "))
[(list x y) (cons x y)])))
(define (bounding-box locs)
(match locs
[(list (cons xs ys) ...)
(list (cons (apply min xs) (apply max ys))
(cons (apply max xs) (apply min ys)))]))
(define bbox (bounding-box locs))
(define (manhattan-dist loca locb)
(match (list loca locb)
[(list (cons xa ya) (cons xb yb))
(+ (abs (- xa xb)) (abs (- ya yb)))]))
(define (closest-to pt locs)
(match (sort (map (λ (loc) (cons (manhattan-dist pt loc) loc)) locs) < #:key car)
[(list* (cons score _) (cons score2 _) _) #:when (= score score2) #false] ; because tie
[(cons (cons _ loc) _) loc]))
(define (finite-neighborhoods locs)
(define closest-table (make-hash))
(match-define (list (cons xmin ymax) (cons xmax ymin)) bbox)
(for* ([x (in-range xmin (add1 xmax))]
[y (in-range ymin (add1 ymax))])
(define pt (cons x y))
(define loc (closest-to pt locs))
(when loc
(if (or (= x xmin) (= x xmax) (= y ymin) (= y ymax)) ; on edge, therefore infinite
(hash-set! closest-table loc #f) ; invalidate loc
(hash-update! closest-table loc (λ (val) (and val (cons pt val))) null))))
(filter values (hash-values closest-table)))
(define ()
(apply max (map length (finite-neighborhoods locs))))
(define (region locs target-dist)
(match-define (list (cons xmin ymax) (cons xmax ymin)) bbox)
(for*/list ([x (in-range xmin (add1 xmax))]
[y (in-range ymin (add1 ymax))]
[pt (in-value (cons x y))]
[total-dist (in-value (for/sum ([loc (in-list locs)])
(manhattan-dist pt loc)))]
#:when (< total-dist target-dist))
pt))
(define (★★)
(length (region locs 10000)))
(module+ test
(require rackunit)
(check-equal? (time ()) 6047)
(check-equal? (time (★★)) 46320))

@ -0,0 +1,50 @@
165, 169
334, 217
330, 227
317, 72
304, 232
115, 225
323, 344
161, 204
316, 259
63, 250
280, 205
84, 282
271, 158
190, 296
106, 349
171, 178
203, 108
89, 271
193, 254
111, 210
341, 343
349, 311
143, 172
170, 307
128, 157
183, 315
211, 297
74, 281
119, 164
266, 345
184, 62
96, 142
134, 61
117, 52
318, 72
338, 287
61, 215
323, 255
93, 171
325, 249
183, 171
71, 235
329, 306
322, 219
151, 298
180, 255
336, 291
72, 300
223, 286
179, 257

@ -2,9 +2,11 @@
#;(define ()
)
#;()
#;(define (★★)
)
#;(★★)
#;(module+ test
(require rackunit)