80 lines
2 KiB
Racket
80 lines
2 KiB
Racket
#lang racket
|
|
|
|
(module+ test
|
|
(require rackunit))
|
|
|
|
(define (read-input filename)
|
|
(map string->tile (file->lines filename)))
|
|
|
|
(define (string->tile str)
|
|
(path->tile (map string->symbol (regexp-match* #rx"(e|w|se|sw|ne|nw)" str))))
|
|
|
|
(define (path->tile path)
|
|
(define-values (q r)
|
|
(for/fold ([q 0]
|
|
[r 0])
|
|
([s (in-list path)])
|
|
(match s
|
|
['e (values (add1 q) r)]
|
|
['ne (values (add1 q) (sub1 r))]
|
|
['nw (values q (sub1 r))]
|
|
['w (values (sub1 q) r)]
|
|
['sw (values (sub1 q) (add1 r))]
|
|
['se (values q (add1 r))])))
|
|
(list q r))
|
|
|
|
(define (initial-grid tiles)
|
|
(define grid (make-hash))
|
|
(for ([tile (in-list tiles)])
|
|
(hash-update! grid tile not #f))
|
|
grid)
|
|
|
|
(define (count-alive grid)
|
|
(for/sum ([(k v) (in-hash grid)]
|
|
#:when v)
|
|
1))
|
|
|
|
(define (part1 filename)
|
|
(define tiles (read-input filename))
|
|
(count-alive (initial-grid tiles)))
|
|
|
|
(module+ test
|
|
(check-equal? (part1 "test") 10))
|
|
|
|
(module+ main
|
|
(displayln (part1 "input")))
|
|
|
|
(define (count-alive-neighbours grid tile)
|
|
(define q (car tile))
|
|
(define r (cadr tile))
|
|
(for*/sum ([i (in-range -1 2)]
|
|
[j (in-range -1 2)]
|
|
#:unless (= 0 i j)
|
|
#:unless (= 2 (abs (+ i j)))
|
|
#:when (hash-ref grid (list (+ q i) (+ r j)) #f))
|
|
1))
|
|
|
|
(define (step grid)
|
|
(define size (+ 2 (apply max (flatten (hash-keys grid)))))
|
|
(for*/hash ([q (in-range (- size) size)]
|
|
[r (in-range (- size) size)])
|
|
(define color (hash-ref grid (list q r) #f))
|
|
(define n (count-alive-neighbours grid (list q r)))
|
|
(values (list q r)
|
|
(cond
|
|
[(and color (or (= 0 n) (> n 2))) #f]
|
|
[(and (not color) (= 2 n)) #t]
|
|
[else color]))))
|
|
|
|
(define (part2 filename)
|
|
(define tiles (read-input filename))
|
|
(count-alive
|
|
(for/fold ([grid (initial-grid tiles)])
|
|
([i (in-range 100)])
|
|
(step grid))))
|
|
|
|
(module+ test
|
|
(check-equal? (part2 "test") 2208))
|
|
|
|
(module+ main
|
|
(displayln (part2 "input")))
|