day 24: use complex numbers for great faste
This commit is contained in:
parent
b80c8d7b6b
commit
c0c11034af
37
24.rkt
37
24.rkt
|
@ -4,16 +4,8 @@
|
||||||
|
|
||||||
;; solution for day 24
|
;; solution for day 24
|
||||||
|
|
||||||
;; constraint: x+y+z = 0
|
(define *dirs* (hash 'e 1-1i 'ne 1 'nw +1i 'w -1+1i 'sw -1 'se -1i))
|
||||||
;; this could be formalized with a contract but part2 is already slow enough tbh
|
(define *dirs-values* (hash-values *dirs*))
|
||||||
(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 (paths->tiles input)
|
(define (paths->tiles input)
|
||||||
;; white is #f
|
;; white is #f
|
||||||
|
@ -21,8 +13,8 @@
|
||||||
(define tiles (make-hash))
|
(define tiles (make-hash))
|
||||||
(for ([path (in-list input)])
|
(for ([path (in-list input)])
|
||||||
(define posn
|
(define posn
|
||||||
(for/fold ([posn (hex 0 0 0)]) ([p (in-list path)])
|
(for/fold ([posn 0]) ([p (in-list path)])
|
||||||
(hex+ posn (hash-ref *dirs* p))))
|
(+ posn (hash-ref *dirs* p))))
|
||||||
(hash-update! tiles posn not #f))
|
(hash-update! tiles posn not #f))
|
||||||
tiles)
|
tiles)
|
||||||
|
|
||||||
|
@ -35,19 +27,14 @@
|
||||||
(define (part2 input)
|
(define (part2 input)
|
||||||
(define tiles (paths->tiles input))
|
(define tiles (paths->tiles input))
|
||||||
|
|
||||||
(define neighbors-cache (make-hash))
|
|
||||||
|
|
||||||
(define (step tiles radius)
|
(define (step tiles radius)
|
||||||
(define new-tiles (make-hash))
|
(define new-tiles (hash-copy tiles))
|
||||||
(for* ([x (in-range (- radius) (add1 radius))] [y (in-range (- radius) (add1 radius))]
|
(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 (make-rectangular x y))
|
||||||
(define thispos (hex x y z))
|
|
||||||
(define thistile (hash-ref tiles thispos #f))
|
(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
|
(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
|
(hash-set! new-tiles thispos
|
||||||
(match* (thistile num-blacks)
|
(match* (thistile num-blacks)
|
||||||
[(#t (or 0 (not (or 1 2)))) #f]
|
[(#t (or 0 (not (or 1 2)))) #f]
|
||||||
|
@ -56,13 +43,11 @@
|
||||||
[(#f _) #f])))
|
[(#f _) #f])))
|
||||||
new-tiles)
|
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))))
|
(hash-keys tiles))))
|
||||||
(begin0
|
|
||||||
(count-black
|
(count-black
|
||||||
(for/fold ([tiles tiles]) ([i (in-range 100)] [radius (in-range (add1 radius) +inf.0)])
|
(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)))
|
(step tiles radius))))
|
||||||
(printf "\r\1b[Kdone\n")))
|
|
||||||
|
|
||||||
;; parse input file
|
;; parse input file
|
||||||
(define (parse fname)
|
(define (parse fname)
|
||||||
|
|
Loading…
Reference in New Issue