aboutsummaryrefslogtreecommitdiff
path: root/2022/day-12/day-12.rkt
blob: 5e0c365ed11c15e52b28bb5ba84c19f59ec9dbf1 (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
#lang racket

(require advent-of-code
         fancy-app
         graph)

(define raw-terrain (fetch-aoc-input (find-session) 2022 12 #:cache #true))
(define special-points (make-hash))

(define terrain-mesh
  (for*/hash ([(row x) (in-indexed (string-split raw-terrain))] [(col y) (in-indexed row)])
    (case col
      [(#\S)
       (hash-set! special-points 'start (cons x y))
       (values (cons x y) 0)]
      [(#\E)
       (hash-set! special-points 'end (cons x y))
       (values (cons x y) 25)]
      [else (values (cons x y) (- (char->integer col) (char->integer #\a)))])))

(define (neighbors p)
  (match-define (cons x y) p)
  (for*/list ([dx (in-list '(-1 0 1))]
              [dy (in-list '(-1 0 1))]
              #:when (= 1 (abs (+ dx dy)))
              #:do [(define p (cons (+ x dx) (+ y dy)))]
              #:when (hash-has-key? terrain-mesh p))
    p))

(define paths
  (directed-graph (for*/list ([p (in-list (hash-keys terrain-mesh))]
                              [neighbor (in-list (neighbors p))]
                              #:unless (> (sub1 (hash-ref terrain-mesh neighbor))
                                          (hash-ref terrain-mesh p)))
                    (list p neighbor))))

;; part 1
(time (match-define-values (distances _) (bfs paths (hash-ref special-points 'start)))
      (hash-ref distances (hash-ref special-points 'end)))

;; part 2
(time (for/lists
       (lengths #:result (apply min lengths))
       ([start (in-list (hash-keys terrain-mesh))] #:when (= 0 (hash-ref terrain-mesh start)))
       (match-define-values (distances _) (bfs paths start))
       (hash-ref distances (hash-ref special-points 'end))))