38 lines
1.5 KiB
Racket
38 lines
1.5 KiB
Racket
#lang racket
|
|
|
|
(require (rename-in (except-in graph transpose)
|
|
[get-neighbors get-neighbours])
|
|
"../lib.rkt")
|
|
|
|
(define input (problem-input 7))
|
|
|
|
(define (strings->graphs bags)
|
|
(let ([contained (weighted-graph/directed '())]
|
|
[contains (weighted-graph/directed '())])
|
|
(for ([bag bags])
|
|
(match-let ([(list _ outer inners) (regexp-match #rx"^(.+) bags contain (.+).$" bag)])
|
|
(for ([inner (string-split inners ",")])
|
|
(match inner
|
|
[(regexp #px"(\\d+) (.+) bags?" (list _ count inner))
|
|
(add-directed-edge! contained inner outer (string->number count))
|
|
(add-directed-edge! contains outer inner (string->number count))]
|
|
[else (add-vertex! contained outer)
|
|
(add-vertex! contains outer)]))))
|
|
(values contained contains)))
|
|
|
|
(define (count-bags graph source)
|
|
(let ([neighbours (get-neighbours graph source)])
|
|
(apply + 1 (map (λ (neighbour)
|
|
(let ([weight (edge-weight graph source neighbour)])
|
|
(* weight (count-bags graph neighbour))))
|
|
neighbours))))
|
|
|
|
(define-values (part1 part2)
|
|
(let*-values ([(contained contains) (strings->graphs input)]
|
|
[(bfs-shiny-gold pred) (bfs contained "shiny gold")]
|
|
[(reachables) (count (λ~> cdr (!= +inf.0)) (hash->list bfs-shiny-gold))]
|
|
[(total-bags) (count-bags contains "shiny gold")])
|
|
(values (sub1 reachables) (sub1 total-bags))))
|
|
|
|
(show-solution part1 part2)
|