aboutsummaryrefslogtreecommitdiff
path: root/aoc2023-other/day-22/day-22.rkt
diff options
context:
space:
mode:
authorHJ <thechairman@thechairman.info>2023-12-22 11:11:58 -0500
committerHJ <thechairman@thechairman.info>2023-12-22 11:11:58 -0500
commit7e81b8f2e98eaea4ec0da1193b5aed492d0a3c3a (patch)
tree625848009c4b17809b790c5c7c8bac6cff59ed05 /aoc2023-other/day-22/day-22.rkt
parent67d98ce7a5f9bb781e759cc6af11be95d9073a1a (diff)
downloadgleam_aoc-7e81b8f2e98eaea4ec0da1193b5aed492d0a3c3a.tar.gz
gleam_aoc-7e81b8f2e98eaea4ec0da1193b5aed492d0a3c3a.zip
day 22 racket complete
Diffstat (limited to 'aoc2023-other/day-22/day-22.rkt')
-rw-r--r--aoc2023-other/day-22/day-22.rkt104
1 files changed, 104 insertions, 0 deletions
diff --git a/aoc2023-other/day-22/day-22.rkt b/aoc2023-other/day-22/day-22.rkt
new file mode 100644
index 0000000..93c77f2
--- /dev/null
+++ b/aoc2023-other/day-22/day-22.rkt
@@ -0,0 +1,104 @@
+#lang racket
+
+(require advent-of-code
+ threading
+ data/applicative
+ data/monad
+ megaparsack
+ megaparsack/text
+ racket/hash)
+
+(struct posn (x y z) #:transparent)
+(struct block (n from to) #:transparent)
+
+(define input (fetch-aoc-input (find-session) 2023 22 #:cache #true))
+
+(define coordinate/p
+ (do [coords <- (many/p integer/p #:sep (char/p #\,) #:min 3 #:max 3)] (pure (apply posn coords))))
+
+(define block/p (do [from <- coordinate/p] (char/p #\~) [to <- coordinate/p] (pure (cons from to))))
+
+(define starting-blocks
+ (~> (for/list ([line (in-list (string-split input "\n"))]
+ [n (in-naturals)])
+ (match-define (cons from to) (parse-result! (parse-string block/p line)))
+ (block n from to))
+ (sort < #:key (λ~> block-from posn-z))))
+
+(define (all-in-cross-section-at-level b z)
+ (match-define (block _ (posn x1 y1 _) (posn x2 y2 _)) b)
+ (for*/list ([x (in-inclusive-range x1 x2)]
+ [y (in-inclusive-range y1 y2)])
+ (posn x y z)))
+
+(define (place-block-at-level b h dz)
+ (match-define (block n (posn x1 y1 z1) (posn x2 y2 z2)) b)
+ (define now-occupied
+ (for*/hash ([x (in-inclusive-range x1 x2)]
+ [y (in-inclusive-range y1 y2)]
+ [z (in-inclusive-range dz (+ dz (- z2 z1)))])
+ (values (posn x y z) n)))
+ (hash-union h now-occupied))
+
+(define (find-lowest-level b h [z (~> b block-from posn-z)])
+ (cond
+ [(= z 0)
+ (place-block-at-level b h 1)]
+ [(findf (curry hash-has-key? h) (all-in-cross-section-at-level b z))
+ (place-block-at-level b h (add1 z))]
+ [else
+ (find-lowest-level b h (sub1 z))]))
+
+(define blocks-in-space (foldl find-lowest-level (hash) starting-blocks))
+(define block-positions
+ (for/fold ([placed-blocks (hash)])
+ ([(p n) (in-hash blocks-in-space)])
+ (hash-update placed-blocks n (curryr set-add p) (set))))
+
+(define (down-one p)
+ (match p
+ [(posn x y z) (posn x y (sub1 z))]))
+
+(define supporting-blocks
+ (for/hash ([(n-id n-posns) (in-hash block-positions)])
+ (values n-id
+ (for*/set ([(m-id m-posns) (in-hash block-positions)]
+ #:unless (= n-id m-id)
+ [m-posn (in-set m-posns)]
+ #:when (set-member? n-posns (down-one m-posn)))
+ m-id))))
+
+(define supported-by-blocks
+ (for/hash ([n-id (in-hash-keys supporting-blocks)])
+ (define supporters
+ (~> (for*/set
+ ([(m-id m-supporting) (in-hash supporting-blocks)]
+ #:unless (= n-id m-id)
+ #:when (set-member? m-supporting n-id))
+ m-id)
+ ((λ (s) (if (set-empty? s) (set 'ground) s)))))
+ (values n-id supporters)))
+
+;; part 1
+(define vulnerable-blocks
+ (for/list ([n-id (in-range (length starting-blocks))]
+ #:when (for/or ([m-supported-by (in-hash-values supported-by-blocks)])
+ (set-empty? (set-remove m-supported-by n-id))))
+ n-id))
+(- (length starting-blocks) (length vulnerable-blocks))
+
+;; part 2
+(for/sum ([n (in-list vulnerable-blocks)])
+ (for/fold ([fallen (set n)]
+ [bricks (set n)]
+ #:result (~> fallen set-count sub1))
+ ([_ (in-naturals)])
+ #:break (set-empty? bricks)
+ (define bricks-above
+ (for*/set
+ ([brick (in-set bricks)]
+ [supporting (in-set (hash-ref supporting-blocks brick))]
+ #:when (for/and ([supports (in-set (hash-ref supported-by-blocks supporting))])
+ (set-member? fallen supports)))
+ supporting))
+ (values (set-union fallen bricks-above) bricks-above))) \ No newline at end of file