You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
3.5 KiB
Racket

#lang racket
(define SIZE 10);
(define (map-map f lst) ; map . map
(map (λ (x) (map (λ (y) (f y)) x)) lst))
(define (char->num chr) ; i hate this
(second (assoc chr (list '(#\0 0) '(#\1 1) '(#\2 2) '(#\3 3) '(#\4 4) '(#\5 5) '(#\6 6) '(#\7 7) '(#\8 8) '(#\9 9)))))
(define (subtract l1 l2) ; retun list of items that are only in l1
(filter (λ (x) (not (member x l2))) l1))
(define grid ; file -> flat vector of the grid digits
(list->vector
(flatten
(map-map char->num
(map string->list
(file->lines "day11.txt"))))))
(define (display-grid grid)
(for-each (λ (i)
(printf "~s " (vector-ref grid i))
(if (= 0 (modulo (add1 i) SIZE)) (printf "~n") (printf "")))
(range 0 (* SIZE SIZE))))
(define (neighbors idx) ; find all the neighboring indicies, filtering out out-of-bounds
(filter (λ (idx) (and (>= idx 0) (< idx (* SIZE SIZE)))) ; remove ones off the top or bottom of board
(filter identity ; remove #f
(flatten (list (if (= (modulo idx SIZE) 0) #f ; if it's on the left edge, #f
(list (- idx (add1 SIZE)) (+ idx (sub1 SIZE)) (sub1 idx)))
(if (= (modulo (add1 idx) SIZE) 0) #f ; if it's on the right edge, #f
(list (- idx (sub1 SIZE)) (+ idx (add1 SIZE)) (add1 idx)))
(list (- idx SIZE) (+ idx SIZE)))))))
(define (flash grid tens seent flash-count) ; recursively flash tens
(for-each (λ (i) (hash-set! seent i #t)) tens) ; mark these tens as having been seen
(let* ([ns (flatten (map neighbors tens))] ; find all the neighbors of the tens
[ns-filtered (filter (λ (i) (not (hash-has-key? seent i))) ns)] ; filter out the ones we've flashed
[new-flash-count (+ flash-count (length tens))])
(for-each (λ (i) (vector-set! grid i (add1 (vector-ref grid i)))) ns-filtered) ; add 1 to all the neighbors
(let* ([new-tens (remove-duplicates (filter (λ (x) (<= 10 (vector-ref grid x))) ns-filtered))])
(if (< 0 (length new-tens))
(flash grid new-tens seent new-flash-count) ; if so, flash em
(list new-flash-count (vector-map! (λ (x) (if (>= x 10) 0 x)) grid)))))) ; otherwise set our 10s to 0 and return the vector
(define (vector-find vect proc) ; returns list of indicies where val is found in vect
(foldr (λ (i acc) (if (proc (vector-ref vect i)) (cons i acc) acc)) '() (range 0 (* SIZE SIZE))))
(define (step grid) ; grid is actually '(count grid)....
(let* ([g (second grid)]
[flash-count (first grid)]
[incd (vector-map add1 g)]
[seent (make-hash)]
[tens (vector-find incd (λ (n) (>= n 10)))]
[res (flash incd tens seent flash-count)])
res))
(define part1
(let loop ([n 100] [g grid] [flash-count 0])
(if (= n 0)
(list g flash-count)
(let* ([res (step (list flash-count g))]
[new-count (first res)]
[new-grid (second res)])
(loop (sub1 n) new-grid new-count)))))
part1
(display-grid (first part1))
(define (all-flashing? grid)
(= 100
(vector-length (vector-filter (λ (x) (= x 0)) grid))))
(define part2
(+ 1 (let loop ([n 0] [g grid] [flash-count 0])
(let* ([res (step (list flash-count g))]
[new-count (first res)]
[new-grid (second res)])
(if (all-flashing? new-grid)
n
(loop (add1 n) new-grid new-count))))))
part2