From 50609b0ab947956a63920c88395edd8ae4ad98e9 Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Tue, 24 Dec 2019 01:00:53 -0800 Subject: [PATCH] Day 24: Part 1 done, part 2 is incorrect. --- input/24.txt | 5 ++ lib.rkt | 28 ++++++++- src/24.rkt | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 input/24.txt create mode 100644 src/24.rkt diff --git a/input/24.txt b/input/24.txt new file mode 100644 index 0000000..53734f9 --- /dev/null +++ b/input/24.txt @@ -0,0 +1,5 @@ +###.. +.##.. +#.... +##..# +.###. \ No newline at end of file diff --git a/lib.rkt b/lib.rkt index 2eea065..d1355f2 100644 --- a/lib.rkt +++ b/lib.rkt @@ -38,7 +38,10 @@ transpose list->queue + vector-first + vector-last vector-ref* + vector-grid-ref* vector-set!* hash->vector vector->hash) @@ -243,6 +246,14 @@ ;; Vector helpers ;; +;; vector-first : (vectorof any) -> any +(define (vector-first vec) + (vector-ref vec 0)) + +;; vector-last : (vectorof any) -> any +(define (vector-last vec) + (vector-ref vec (sub1 (vector-length vec)))) + ;; vector-ref* : (vectorof any) -> number -> any -> any ;; Same as list-ref, except a default value is provided ;; if the index is beyond the length of the list. @@ -251,9 +262,24 @@ failure-result (vector-ref vec pos))) +;; vector-grid-ref* : (vectorof (vectorof any)) -> (list number number) -> any -> any +;; Given coordinates (x, y), in the yth vector, find the xth element. +;; If either x or y are beyond the indices of the vectors, +;; return the default value provided. +(define (vector-grid-ref* grid coord failure-result) + (match-let ([(list x y) coord] + [y-len (vector-length grid)]) + (if (or (< y 0) (>= y y-len)) + failure-result + (let* ([row (vector-ref grid y)] + [x-len (vector-length row)]) + (if (or (< x 0) (>= x x-len)) + failure-result + (vector-ref row x)))))) + ;; vector-set!* : (vectorof any) -> number -> any -> (vectorof any) ;; Set the value at given index in a new vector, then return that vector -;; If the index is beyond the length of the vector, +;; If the index is beyond the indices of the vector, ;; a vector that can accomodate that index is returned, ;; with all the original elements and the element at the index set (define (vector-set!* vec pos v) diff --git a/src/24.rkt b/src/24.rkt new file mode 100644 index 0000000..b9991b4 --- /dev/null +++ b/src/24.rkt @@ -0,0 +1,167 @@ +#lang racket + +(require racket/set + "../lib.rkt") + +(define input + (problem-input 24)) + +(define width + (string-length (car input))) + +(define height + (length input)) + +(define mid-x + (round (/ width 2))) + +(define mid-y + (round (/ height 2))) + +(define vector-grid + (list->vector (map (∘ list->vector string->list) input))) + +(define (make-empty-grid) + (build-vector height (λ (_) (make-vector width #\.)))) + +(define (outer-edge? coord) + (match-let ([(list x y) coord]) + (or (= x 0) (= y 0) + (= x (sub1 width)) (= y (sub1 height))))) + +(define (inner-edge? coord) + (match-let ([(list x y) coord]) + (or (= x mid-x) + (= y mid-y)))) + +(define (edge-bugs grid side) + (match side + ['U (vector-count (∂ char=? #\#) (vector-ref grid 0))] + ['D (vector-count (∂ char=? #\#) (vector-ref grid (sub1 height)))] + ['L (vector-count (∂ char=? #\#) (vector-map (∂ vector-first) grid))] + ['R (vector-count (∂ char=? #\#) (vector-map (∂ vector-last) grid))])) + +(define (edges-bugs? grid) + (!= 0 (+ (edge-bugs grid 'U) + (edge-bugs grid 'D) + (edge-bugs grid 'L) + (edge-bugs grid 'R)))) + +(define (middle-bug grid side) + (match side + ['U (if (char=? #\# (vector-grid-ref* grid (list mid-x (sub1 mid-y)) #\.)) 1 0)] + ['D (if (char=? #\# (vector-grid-ref* grid (list mid-x (add1 mid-y)) #\.)) 1 0)] + ['L (if (char=? #\# (vector-grid-ref* grid (list (sub1 mid-x) mid-y) #\.)) 1 0)] + ['R (if (char=? #\# (vector-grid-ref* grid (list (add1 mid-x) mid-y) #\.)) 1 0)])) + +(define (middle-bugs? grid) + (!= 0 (+ (middle-bug grid 'U) + (middle-bug grid 'D) + (middle-bug grid 'L) + (middle-bug grid 'R)))) + +(define (adjacent-bugs grid coord) + (match-let* ([(list x y) coord] + [U (vector-grid-ref* grid (list x (sub1 y)) #\.)] + [D (vector-grid-ref* grid (list x (add1 y)) #\.)] + [L (vector-grid-ref* grid (list (sub1 x) y) #\.)] + [R (vector-grid-ref* grid (list (add1 x) y) #\.)]) + (count (∂ char=? #\#) (list U D L R)))) + +(define (adjacent-bugs* grids level coord) + (match-let* ([(list x y) coord] + [grid (list-ref grids level)] + [level-bugs (adjacent-bugs grid coord)]) + (cond + [(and (outer-edge? coord) (> level 0)) + (let* ([outer-grid (list-ref grids (sub1 level))]) + (cond + [(= x 0) + (+ level-bugs (middle-bug outer-grid 'L))] + [(= y 0) + (+ level-bugs (middle-bug outer-grid 'U))] + [(= x (sub1 width)) + (+ level-bugs (middle-bug outer-grid 'R))] + [(= y (sub1 height)) + (+ level-bugs (middle-bug outer-grid 'D))]))] + [(and (inner-edge? coord) (< level (sub1 (length grids)))) + (let* ([inner-grid (list-ref grids (add1 level))]) + (cond + [(and (= x mid-x) (< y mid-y)) + (+ level-bugs (edge-bugs inner-grid 'U))] + [(and (= x mid-x) (> y mid-y)) + (+ level-bugs (edge-bugs inner-grid 'D))] + [(and (= y mid-y) (< x mid-x)) + (+ level-bugs (edge-bugs inner-grid 'L))] + [(and (= y mid-y) (> x mid-x)) + (+ level-bugs (edge-bugs inner-grid 'R))] + [else level-bugs]))] + [else level-bugs]))) + +(define (step grid) + (let ([new-grid (make-empty-grid)]) + (for ([coord (cartesian-product (range 0 width) (range 0 height))]) + (match-let* ([(list x y) coord] + [char (vector-ref (vector-ref grid y) x)] + [bug-count (adjacent-bugs grid coord)] + [next-char + (match char + [#\. #:when (<= 1 bug-count 2) #\#] + [#\# #:when (!= 1 bug-count) #\.] + [else char])]) + (vector-set! (vector-ref new-grid y) x next-char))) + new-grid)) + +(define (step* grids) + (let* ([grids* + (foldl + (λ (level grid grids*) + (let ([new-grid (make-empty-grid)]) + (for ([coord (cartesian-product (range 0 width) (range 0 height))]) + (match-let* ([(list x y) coord] + [char (vector-ref (vector-ref grid y) x)] + [bug-count (adjacent-bugs* grids level coord)] + [next-char + (match char + [#\. #:when (<= 1 bug-count 2) #\#] + [#\# #:when (!= 1 bug-count) #\.] + [else char])]) + (vector-set! (vector-ref new-grid y) x next-char))) + (cons new-grid grids*))) + '() (range 0 (length grids)) grids)] + [grids* (if (edges-bugs? (first grids*)) + (cons (make-empty-grid) grids*) + grids*)] + [grids* (if (middle-bugs? (last grids*)) + (append grids* (list (make-empty-grid))) + grids*)]) + grids*)) + +(define (biodiversity grid) + (let ([list-grid (append* (map vector->list (vector->list grid)))]) + (sum (map (λ (char i) + (if (char=? char #\#) + (expt 2 i) 0)) + list-grid (range 0 (length list-grid)))))) + +(define (total-bugs grids) + (sum (map (λ (grid) + (sum (vector->list (vector-map (∂ vector-count (∂ char=? #\#)) grid)))) + grids))) + +(define part1 + (let loop ([grid vector-grid] + [set (set vector-grid)]) + (let ([next-grid (step grid)]) + (if (set-member? set next-grid) + (biodiversity next-grid) + (loop next-grid (set-add set next-grid)))))) + +(define part2 + (let loop ([count 0] + [grids (list (make-empty-grid) vector-grid (make-empty-grid))]) + (if (= count 10) + (total-bugs grids) + (loop (add1 count) (step* grids))))) + +(show-solution part1 part2) \ No newline at end of file