-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathday09.rkt
58 lines (50 loc) · 1.53 KB
/
day09.rkt
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
#lang racket/base
(require racket/list
racket/set)
(define data
(call-with-input-file "day09.txt"
(lambda (in)
(for/fold ([points (hash)])
([line (in-lines in)]
[i (in-naturals 1)])
(for/fold ([points points])
([c (in-string line)]
[j (in-naturals 1)])
(define d (string->number (string c)))
(hash-set points (cons i j) d))))))
(define (adjacent-positions pos)
(define i (car pos))
(define j (cdr pos))
`((,(sub1 i) . ,j)
(,i . ,(sub1 j))
(,i . ,(add1 j))
(,(add1 i) . ,j)))
(define (low-point? pos)
(define p (hash-ref data pos #f))
(and p (for/and ([q (in-list (adjacent-positions pos))])
(< p (hash-ref data q +inf.0)))))
(define part1
(for*/sum ([pos (in-hash-keys data)] #:when (low-point? pos))
(add1 (hash-ref data pos))))
(define (basin-size pos)
(define seen (mutable-set pos))
(let loop ([pos pos])
(define v (hash-ref data pos 9))
(cond
[(= v 9) 0]
[else
(add1
(for/sum ([pos (in-list (adjacent-positions pos))]
#:unless (set-member? seen pos)
#:when (< v (hash-ref data pos -inf.0)))
(set-add! seen pos)
(loop pos)))])))
(define part2
(time
(let ([basins (for/list ([pos (in-hash-keys data)] #:when (low-point? pos))
(basin-size pos))])
(apply * (take (sort basins >) 3)))))
(module+ test
(require rackunit)
(check-= part1 489 0)
(check-= part2 1056330 0))