119 lines
3.4 KiB
Racket
119 lines
3.4 KiB
Racket
#lang racket
|
|
|
|
(module+ test
|
|
(require rackunit))
|
|
|
|
(module+ main
|
|
(displayln "Day 11"))
|
|
|
|
(define (matrix-ref mat i j default)
|
|
(define n (vector-length mat))
|
|
(define m (vector-length (vector-ref mat 0)))
|
|
(if (or (< i 0) (<= n i) (< j 0) (<= m j))
|
|
default
|
|
(vector-ref (vector-ref mat i) j)))
|
|
|
|
(define (matrix-set! mat i j v)
|
|
(vector-set! (vector-ref mat i) j v))
|
|
|
|
(define (matrix-copy mat)
|
|
(for/vector ([l (in-vector mat)])
|
|
(vector-copy l)))
|
|
|
|
(define (display-state state)
|
|
(for ([l (in-vector state)])
|
|
(displayln (list->string (vector->list l))))
|
|
(displayln ""))
|
|
|
|
(define (parse-line str)
|
|
(list->vector (string->list str)))
|
|
|
|
(define (read-input filename)
|
|
(with-input-from-file filename
|
|
(lambda ()
|
|
(for/vector ([line (in-lines)])
|
|
(parse-line line)))))
|
|
|
|
(define (update-seat-neighbours state x y)
|
|
(define neighbours (for*/sum ([i '(-1 0 1)]
|
|
[j '(-1 0 1)]
|
|
#:unless (= 0 i j))
|
|
(if (eq? #\# (matrix-ref state (+ x i) (+ y j) #\.)) 1 0)))
|
|
(define s (matrix-ref state x y #\.))
|
|
(cond
|
|
[(and (eq? s #\L) (= neighbours 0)) #\#]
|
|
[(and (eq? s #\#) (>= neighbours 4)) #\L]
|
|
[else s]))
|
|
|
|
(define (update-state state update-seat-fn)
|
|
(define n (vector-length state))
|
|
(define m (vector-length (vector-ref state 0)))
|
|
(define new-state (matrix-copy state))
|
|
(for* ([x (in-range n)]
|
|
[y (in-range m)])
|
|
(matrix-set! new-state x y (update-seat-fn state x y)))
|
|
new-state)
|
|
|
|
(define (count-occupied state)
|
|
(for*/sum ([l (in-vector state)]
|
|
[v (in-vector l)]
|
|
#:when (eq? v #\#))
|
|
1))
|
|
|
|
(define (part1 filename)
|
|
(define input (read-input filename))
|
|
(define n (vector-length input))
|
|
(define m (vector-length (vector-ref input 0)))
|
|
(define-values (prev final)
|
|
(for/fold ([prev-state 0]
|
|
[state input])
|
|
([i (in-naturals)]
|
|
#:break (equal? prev-state state))
|
|
(define new-state (update-state state update-seat-neighbours))
|
|
(values state new-state)))
|
|
(count-occupied final))
|
|
|
|
(module+ test
|
|
(check-equal? (part1 "test") 37))
|
|
|
|
(module+ main
|
|
(displayln (part1 "input")))
|
|
|
|
(define (visible state x y dx dy)
|
|
(define n (vector-length state))
|
|
(define m (vector-length (vector-ref state 0)))
|
|
(let loop ([u (+ x dx)]
|
|
[v (+ y dy)])
|
|
(cond
|
|
[(or (< u 0) (< v 0) (<= n u) (<= m v)) 0]
|
|
[(eq? #\L (matrix-ref state u v #\.)) 0]
|
|
[(eq? #\# (matrix-ref state u v #\.)) 1]
|
|
[else (loop (+ u dx) (+ v dy))])))
|
|
|
|
(define (update-seat-visible state x y)
|
|
(define n-visible (apply + (for*/list ([dx '(-1 0 1)]
|
|
[dy '(-1 0 1)]
|
|
#:unless (= 0 dx dy))
|
|
(visible state x y dx dy))))
|
|
(define s (matrix-ref state x y #\.))
|
|
(cond
|
|
[(and (eq? s #\L) (= n-visible 0)) #\#]
|
|
[(and (eq? s #\#) (>= n-visible 5)) #\L]
|
|
[else s]))
|
|
|
|
(define (part2 filename)
|
|
(define input (read-input filename))
|
|
(define-values (prev final)
|
|
(for/fold ([prev-state 0]
|
|
[state input])
|
|
([i (in-naturals)]
|
|
#:break (equal? prev-state state))
|
|
(define new-state (update-state state update-seat-visible))
|
|
(values state new-state)))
|
|
(count-occupied final))
|
|
|
|
(module+ test
|
|
(check-equal? (part2 "test") 26))
|
|
|
|
(module+ main
|
|
(displayln (part2 "input")))
|