aboutsummaryrefslogtreecommitdiff
path: root/2022/day-16/day-16.rkt
blob: c7fe6544f2f51b9724f3cc4da0022f00c66e211f (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
65
66
67
68
#lang racket

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

(define (process-line str)
  (match str
    [(regexp #px"Valve (\\w\\w) has flow rate=(\\d+); tunnels? leads? to valves? (.+)"
             (list _ name (app string->number rate) (app (string-split _ ", ") valves)))
     (list name rate valves)]))

(define cave-data
  (~> (fetch-aoc-input (find-session) 2022 16 #:cache #true)
      (string-split "\n")
      (map process-line _)))

(define cave-map
  (for*/lists (tunnels #:result (directed-graph tunnels))
              ([valve (in-list cave-data)] #:do [(match-define (list name _ valves) valve)]
                                           [destination (in-list valves)])
              (list name destination)))

(define valve-flows
  (for/hash ([valve (in-list cave-data)]
             #:do [(match-define (list name flow _) valve)]
             #:when (> flow 0))
    (values name flow)))

(define shortest-path-lengths (johnson cave-map))

(define (reachable-destinations start dests minutes-left)
  (for/list ([(dest _) (in-hash dests)]
             #:do [(define travel-time
                     (hash-ref shortest-path-lengths (list start dest) minutes-left))]
             #:when (<= 1 travel-time minutes-left))
    (cons dest travel-time)))

;; part 1
(define (find-best-single-route start
                                [current-pressure 0]
                                [available-valves valve-flows]
                                [minutes-left 30])
  (cond
    [(>= minutes-left 1)
     (for/fold ([running-pressure current-pressure])
               ([candidate (reachable-destinations start available-valves minutes-left)])
       (match-define (cons dest travel-time) candidate)
       (define minutes-left* (- minutes-left (add1 travel-time)))
       (define candidate-pressure
         (find-best-single-route dest
                                 (+ current-pressure (* (hash-ref valve-flows dest) minutes-left*))
                                 (hash-remove available-valves dest)
                                 minutes-left*))
       (if (> candidate-pressure running-pressure) candidate-pressure running-pressure))]
    [else current-pressure]))

(find-best-single-route "AA")

;; part 2
(define (find-best-double-route start
                                [current-pressure 0]
                                [available-valves valve-flows]
                                [minutes-left 30])
  'todo)

(find-best-double-route "AA")