blob: 7950339b1e157557183fe84d76a58eee6098edeb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
#lang racket
(require advent-of-code
threading
algorithms)
(define data (fetch-aoc-input (find-session) 2022 14 #:cache #true))
(define (trace-line-between-points p1 p2)
(match* (p1 p2)
[((list x y1) (list x y2))
(for/list ([y [in-inclusive-range (min y1 y2) (max y1 y2)]])
(cons x y))]
[((list x1 y) (list x2 y))
(for/list ([x [in-inclusive-range (min x1 x2) (max x1 x2)]])
(cons x y))]))
(define all-coordinates
(apply append
(for/list ([formation (in-list (string-split data "\n"))])
(define coord-list
(for/list ([coord-pair (in-list (string-split formation " -> "))])
(for/list ([coord (in-list (string-split coord-pair ","))])
(string->number coord))))
(apply append (adjacent-map trace-line-between-points coord-list)))))
(define rock-structures-hash
(for/hash ([p (in-list all-coordinates)])
(values p 'rock)))
(define max-vertical-distance (~>> all-coordinates (argmax cdr) cdr add1))
(define (open? h x y)
(not (hash-has-key? h (cons x y))))
;; part 1
(define (trace-grain h [pos (cons 500 0)])
(match-define (cons x y) pos)
(cond
[(> y max-vertical-distance) 'break]
[(open? h x (add1 y)) (trace-grain h (cons x (add1 y)))]
[(open? h (sub1 x) (add1 y)) (trace-grain h (cons (sub1 x) (add1 y)))]
[(open? h (add1 x) (add1 y)) (trace-grain h (cons (add1 x) (add1 y)))]
[else (hash-set h (cons x y) 'sand)]))
(for/fold ([h rock-structures-hash] [grains 0] #:result grains) ([_ (in-naturals 1)])
(define h* (trace-grain h))
#:break (eq? h* 'break)
(values h* (add1 grains)))
;; part 2
(define (trace-grain* h [pos (cons 500 0)])
(match-define (cons x y) pos)
(cond
[(= y max-vertical-distance) (hash-set h (cons x y) 'sand)]
[(open? h x (add1 y)) (trace-grain* h (cons x (add1 y)))]
[(open? h (sub1 x) (add1 y)) (trace-grain* h (cons (sub1 x) (add1 y)))]
[(open? h (add1 x) (add1 y)) (trace-grain* h (cons (add1 x) (add1 y)))]
[else (hash-set h (cons x y) 'sand)]))
(for/fold ([h rock-structures-hash] [grains 0] #:result grains) ([_ (in-naturals 1)])
#:break (not (open? h 500 0))
(define h* (trace-grain* h))
(values h* (add1 grains)))
|