advent-of-code/2020/day11/day11.rkt
2024-11-12 21:46:18 +01:00

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")))