about summary refs log tree commit diff
path: root/day12.rkt
blob: d6ce357b051795430d6f2f74a5d19a06cf37b0ff (plain) (blame)
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
#lang racket

(require data/heap)

(struct item (score value) #:transparent)

(define (item<=? x y)
  (<= (item-score x) (item-score y)))

(define start #f)
(define end #f)
(define data (for/vector ([(line x) (in-indexed (file->lines "day12"))])
               (for/vector ([(char y) (in-indexed line)])
                 (case char
                   [(#\S) (set! start (vector x y)) 0]
                   [(#\E) (set! end (vector x y)) 26]
                   [else (- (char->integer char) (char->integer #\a) 0)]))))

(define (neighbors v)
  (for*/list ([x '(-1 0 1)]
              [y '(-1 0 1)]
              #:unless (= x y 0)
              #:when (zero? (* x y))
              #:when (< -1 (+ x (vector-ref v 0)) (vector-length data))
              #:when (< -1 (+ y (vector-ref v 1)) (vector-length
                                                   (vector-ref data 0))))
    (vector (+ x (vector-ref v 0))
            (+ y (vector-ref v 1)))))

(define (height v)
  (vector-ref (vector-ref data (vector-ref v 0)) (vector-ref v 1)))

(define (solve data start fin? comp)
  (define heap (make-heap item<=?))
  (define seen (mutable-set))

  (heap-add! heap (item 0 start))

  (let loop ()
    (if (zero? (heap-count heap))
      #f
      (let* ([step (heap-min heap)]
             [pos (item-value step)])
        (heap-remove-min! heap)
        (if (set-member? seen pos)
          (loop)
          (if (fin? pos)
              (item-score step)             ; done
              (begin
                (set-add! seen pos)
                (for ([n (neighbors pos)])
                  (when (comp (- (height n) (height pos)))
                    ;(displayln n)
                    (heap-add! heap (item (+ 1 (item-score step)) n))))
                (loop))))))))

(solve data start (curry equal? end) (curry >= 1))
;; 447

(solve data end (lambda (pos) (zero? (height pos))) (curry <= -1))
;; 446