day 24: some cleanup

This commit is contained in:
xenia 2020-12-24 00:54:24 -05:00
parent ad7e76345c
commit b80c8d7b6b
1 changed files with 32 additions and 30 deletions

62
24.rkt
View File

@ -4,23 +4,20 @@
;; solution for day 24 ;; solution for day 24
; (define d->r degrees->radians) ;; constraint: x+y+z = 0
; (define (i->e x) (inexact->exact (round x))) ;; this could be formalized with a contract but part2 is already slow enough tbh
(struct hex [x y z] #:transparent) (struct hex [x y z] #:transparent)
(define (hex+ a b) (define (hex+ a b)
(hex (+ (hex-x a) (hex-x b)) (hex (+ (hex-x a) (hex-x b))
(+ (hex-y a) (hex-y b)) (+ (hex-y a) (hex-y b))
(+ (hex-z a) (hex-z b)))) (+ (hex-z a) (hex-z b))))
(define *dirs* (hash (define *dirs* (hash 'e (hex 1 -1 0) 'ne (hex 1 0 -1) 'nw (hex 0 1 -1)
'e (hex 1 -1 0) 'w (hex -1 1 0) 'sw (hex -1 0 1) 'se (hex 0 -1 1)))
'ne (hex 1 0 -1)
'nw (hex 0 1 -1)
'w (hex -1 1 0)
'sw (hex -1 0 1)
'se (hex 0 -1 1)))
(define (paths->tiles input) (define (paths->tiles input)
;; white is #f
;; black is #t
(define tiles (make-hash)) (define tiles (make-hash))
(for ([path (in-list input)]) (for ([path (in-list input)])
(define posn (define posn
@ -29,38 +26,43 @@
(hash-update! tiles posn not #f)) (hash-update! tiles posn not #f))
tiles) tiles)
(define (part1 input) (define (count-black tiles)
;; white is #f
;; black is #t
(define tiles (paths->tiles input))
(for/sum ([(_ v) (in-hash tiles)] #:when v) 1)) (for/sum ([(_ v) (in-hash tiles)] #:when v) 1))
(define (part1 input)
(count-black (paths->tiles input)))
(define (part2 input) (define (part2 input)
(define tiles (paths->tiles input)) (define tiles (paths->tiles input))
(define (step tiles) (define neighbors-cache (make-hash))
(define (step tiles radius)
(define new-tiles (make-hash)) (define new-tiles (make-hash))
(define minx (apply min (map hex-x (hash-keys tiles)))) (for* ([x (in-range (- radius) (add1 radius))] [y (in-range (- radius) (add1 radius))]
(define maxx (apply max (map hex-x (hash-keys tiles)))) [z (in-range (- radius) (add1 radius))] #:when (zero? (+ x y z)))
(define miny (apply min (map hex-y (hash-keys tiles))))
(define maxy (apply max (map hex-y (hash-keys tiles))))
(define minz (apply min (map hex-z (hash-keys tiles))))
(define maxz (apply max (map hex-z (hash-keys tiles))))
(for* ([x (in-range (sub1 minx) (+ maxx 2))] [y (in-range (sub1 miny) (+ maxy 2))] [z (in-range (sub1 minz) (+ maxz 2))] #:when (zero? (+ x y z)))
(define thispos (hex x y z)) (define thispos (hex x y z))
(define thistile (hash-ref tiles thispos #f)) (define thistile (hash-ref tiles thispos #f))
(define num-blacks (for/sum ([t (in-list (hash-values *dirs*))] #:when (hash-ref tiles (hex+ thispos t) #f)) 1)) (define neighbors (hash-ref! neighbors-cache thispos
(thunk (for/list ([t (in-list (hash-values *dirs*))])
(hex+ thispos t)))))
(define num-blacks
(for/sum ([neigh (in-list neighbors)] #:when (hash-ref tiles neigh #f)) 1))
(hash-set! new-tiles thispos (hash-set! new-tiles thispos
(cond (match* (thistile num-blacks)
[(and thistile (or (zero? num-blacks) (> num-blacks 2))) #f] [(#t (or 0 (not (or 1 2)))) #f]
[thistile #t] [(#t _) #t]
[(= num-blacks 2) #t] [(#f 2) #t]
[else #f]))) [(#f _) #f])))
new-tiles) new-tiles)
(define end (for/fold ([tiles tiles]) ([i (in-range 100)]) (displayln i) (step tiles))) (define radius (apply max (map #{max (abs (hex-x %)) (abs (hex-y %)) (abs (hex-z %))}
(hash-keys tiles))))
(for/sum ([(_ v) (in-hash end)] #:when v) 1)) (begin0
(count-black
(for/fold ([tiles tiles]) ([i (in-range 100)] [radius (in-range (add1 radius) +inf.0)])
(printf "\r\x1b[K~a/100..." i) (flush-output) (step tiles radius)))
(printf "\r\1b[Kdone\n")))
;; parse input file ;; parse input file
(define (parse fname) (define (parse fname)