1
+ #lang racket
2
+
3
+ (define LINES (file->lines "day7.txt " ))
4
+
5
+ (struct bag (adjective color) #:transparent )
6
+
7
+ (define (string-split-normalize s sep)
8
+ (map string-normalize-spaces (string-split s sep)))
9
+
10
+ (define (string->words s)
11
+ (string-split s " " ))
12
+
13
+ (define (string->bag-num s)
14
+ (let ([words (string->words s)])
15
+ (cons (apply bag (cdr words))
16
+ (string->number (car words)))))
17
+
18
+ (define (string->bags s)
19
+ (if (string-prefix? s "no " )
20
+ '()
21
+ (map string->bag-num (string-split s ", " ))))
22
+
23
+ (define (string->rule s)
24
+ (match-let* ([cleaned (string-replace (string-replace s #rx"bags? " "" ) ". " "" )]
25
+ [(list left right) (string-split-normalize cleaned "contain " )]
26
+ [left-bag (apply bag (string->words left))]
27
+ [right-bags (string->bags right)])
28
+ (list left-bag right-bags)))
29
+
30
+ (define RULES (apply hash (apply append (map string->rule LINES))))
31
+
32
+ (define (bag-contains? b c)
33
+ (let ([bags (hash-ref RULES b)])
34
+ (if (empty? bags)
35
+ #f
36
+ (if (assoc c bags)
37
+ #t
38
+ (for/or ([candidate (map car bags)])
39
+ (bag-contains? candidate c))))))
40
+
41
+ (count values (map (λ (b) (bag-contains? b (bag "shiny " "gold " ))) (hash-keys RULES)))
42
+
43
+ (define (bag-count b)
44
+ (let ([bags (hash-ref RULES b)])
45
+ (if (empty? bags)
46
+ 0
47
+ (+ (apply + (map cdr bags))
48
+ (for/fold ([sum 0 ])
49
+ ([candidate (map car bags)]
50
+ [count (map cdr bags)])
51
+ (+ sum (* count (bag-count candidate))))))))
52
+
53
+ (bag-count (bag "shiny " "gold " ))
0 commit comments