diff --git a/24.rkt b/24.rkt index b4f5e11..912fa74 100644 --- a/24.rkt +++ b/24.rkt @@ -4,16 +4,8 @@ ;; solution for day 24 -;; constraint: x+y+z = 0 -;; this could be formalized with a contract but part2 is already slow enough tbh -(struct hex [x y z] #:transparent) -(define (hex+ a b) - (hex (+ (hex-x a) (hex-x b)) - (+ (hex-y a) (hex-y b)) - (+ (hex-z a) (hex-z b)))) - -(define *dirs* (hash 'e (hex 1 -1 0) '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 *dirs* (hash 'e 1-1i 'ne 1 'nw +1i 'w -1+1i 'sw -1 'se -1i)) +(define *dirs-values* (hash-values *dirs*)) (define (paths->tiles input) ;; white is #f @@ -21,8 +13,8 @@ (define tiles (make-hash)) (for ([path (in-list input)]) (define posn - (for/fold ([posn (hex 0 0 0)]) ([p (in-list path)]) - (hex+ posn (hash-ref *dirs* p)))) + (for/fold ([posn 0]) ([p (in-list path)]) + (+ posn (hash-ref *dirs* p)))) (hash-update! tiles posn not #f)) tiles) @@ -35,19 +27,14 @@ (define (part2 input) (define tiles (paths->tiles input)) - (define neighbors-cache (make-hash)) - (define (step tiles radius) - (define new-tiles (make-hash)) - (for* ([x (in-range (- radius) (add1 radius))] [y (in-range (- radius) (add1 radius))] - [z (in-range (- radius) (add1 radius))] #:when (zero? (+ x y z))) - (define thispos (hex x y z)) + (define new-tiles (hash-copy tiles)) + (for* ([x (in-range (- radius) (add1 radius))] [y (in-range (- radius) (add1 radius))]) + (define thispos (make-rectangular x y)) (define thistile (hash-ref tiles thispos #f)) - (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)) + (for/sum ([neigh (in-list *dirs-values*)] #:when (hash-ref tiles (+ thispos neigh) #f)) + 1)) (hash-set! new-tiles thispos (match* (thistile num-blacks) [(#t (or 0 (not (or 1 2)))) #f] @@ -56,13 +43,11 @@ [(#f _) #f]))) new-tiles) - (define radius (apply max (map #{max (abs (hex-x %)) (abs (hex-y %)) (abs (hex-z %))} + (define radius (apply max (map #{max (abs (real-part %)) (abs (imag-part %))} (hash-keys tiles)))) - (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"))) + (count-black + (for/fold ([tiles tiles]) ([i (in-range 100)] [radius (in-range (add1 radius) +inf.0)]) + (step tiles radius)))) ;; parse input file (define (parse fname)