aoc2020/7.rkt

72 lines
2.6 KiB
Racket
Raw Normal View History

#lang curly-fn racket
(require "scripts/aoc.rkt")
;; solution for day 7
(define (part1 G wanted)
(define-vertex-property G has-wanted #:init #f)
(do-dfs G
;; only visit when the to vertex is not already marked with has-wanted
#:visit?: (if (and $from (has-wanted $to))
(begin (has-wanted-set! $from #t) #f)
#t)
;; propagate has-wanted if the child has it
#:epilogue: (when (and $from (or (has-wanted $to) (string=? wanted $to)))
(has-wanted-set! $from #t)))
;; count the results
(for/sum ([(_ v) (in-hash (has-wanted->hash))] #:when v) 1))
(define (part2 G wanted)
;; initially, each vertex just counts the weight of itself, which is 1
(define-vertex-property G all-weight #:init 1)
;; accumulates the result in the vertex property tracking all weights
;; adds the total weight of $to multiplied by the edge weight of $from -> $to to the total weight
;; of $from
;; this will be called for each neighbor of $from, and $from's total weight starts at 1
(define (increment $from $to)
(when $from
(all-weight-set! $from
(+ (all-weight $from)
(* (edge-weight G $from $to) (all-weight $to))))))
(do-dfs G
#:order (lambda (_) (list wanted))
;; always check already-visited nodes
#:process-unvisited?: #t
;; add already-visited nodes to the total
#:process-unvisited: (increment $from $to)
;; add nodes we finished visiting to the total
#:epilogue: (increment $from $to))
;; subtract 1 because we counted the shiny gold bag itself, when we only need the weight of
;; what's inside it
(sub1 (all-weight wanted)))
(module+ main
(define input-lines (file->lines "inputs/7"))
(define edges
(apply append
(for/list ([line (in-list input-lines)])
(match line
[(pregexp #px"^([a-z ]+) bags contain ([^\\.]+).$" (list _ src-color contains))
(if (string=? "no other bags" contains)
'()
(for/list ([item (in-list (string-split contains ", "))])
(match item
[(pregexp #px"^([0-9]+) ([a-z ]+) bag[s]?"
(list _ (app string->number number) dst-color))
(list number src-color dst-color)]
[x (error "not shonks" x)])))]
[x (error "not shonks" x)]))))
(define input (weighted-graph/directed edges))
(define wanted "shiny gold")
;; part 1
(answer 7 1 (part1 input wanted))
;; part 2
(answer 7 2 (part2 input wanted))
(displayln "meow"))