diff --git a/21.rkt b/21.rkt index 3964ded..e928b8a 100644 --- a/21.rkt +++ b/21.rkt @@ -4,78 +4,43 @@ ;; solution for day 21 +(struct line [is as] #:transparent) +(struct data [lines all-is all-as tainted] #:transparent) + (define (part1 input) - ; (define edges - ; (for/fold ([edges '()]) ([line (in-list input)]) - ; (match-define (cons ingreds allergs) line) - ; (append edges (for*/list ([i (in-list ingreds)] [a (in-list allergs)]) - ; (list i a))))) - ; (define G (undirected-graph edges)) - ;(define matching (maximum-bipartite-matching G)) - (define all-ingreds (for/fold ([all (set)]) ([line (in-list input)]) - (set-union all (list->set (car line))))) - (define all-allergs (for/fold ([all (set)]) ([line (in-list input)]) - (set-union all (list->set (cdr line))))) - (define tainted (mutable-set)) - (for ([allerg (in-set all-allergs)]) - (define necessary (for/fold ([necessary all-ingreds]) ([line (in-list input)] #:when (member allerg (cdr line))) - (set-intersect necessary (list->set (car line))))) - (set-union! tainted necessary)) - (define untainted (set-subtract all-ingreds tainted)) - (for*/sum ([line (in-list input)] [ingred (in-list (car line))]) - (if (set-member? untainted ingred) 1 0))) + (match-define (data lines all-is all-as tainted) input) + (define untainted (set-subtract all-is (apply set-union (hash-values tainted)))) + (for*/sum ([l (in-list lines)] [i (in-set (line-is l))] #:when (set-member? untainted i)) + 1)) (define (part2 input) - (define all-ingreds (for/fold ([all (set)]) ([line (in-list input)]) - (set-union all (list->set (car line))))) - (define all-allergs (for/fold ([all (set)]) ([line (in-list input)]) - (set-union all (list->set (cdr line))))) - (define tainted (mutable-set)) - (for ([allerg (in-set all-allergs)]) - (define necessary (for/fold ([necessary all-ingreds]) ([line (in-list input)] #:when (member allerg (cdr line))) - (set-intersect necessary (list->set (car line))))) - (set-union! tainted necessary)) - - (define tainthash (for/hash ([a (in-set all-allergs)]) - (values a (for/fold ([is all-ingreds]) ([line (in-list input)] #:when (member a (cdr line))) - (set-intersect is (list->set (filter #{set-member? tainted %} (car line)))))))) - (define edges (for*/list ([k (in-list (hash-keys tainthash))] - [v (in-set (hash-ref tainthash k))]) - (list k v))) - - (pretty-write edges) + (match-define (data lines all-is all-as tainted) input) + (define edges + (for*/list ([(k v*) (in-hash tainted)] [v (in-set v*)]) + (list k v))) (define G (undirected-graph edges)) (define matching (maximum-bipartite-matching G)) - (displayln matching) - (define mhash (for/hash ([item (in-list matching)]) (values (first item) (second item)))) - (displayln mhash) - (define by-allergs (sort (hash-keys mhash) stringlines fname)) - (for/list ([line (in-list lines)]) - (match line - [(pregexp #px"^([^\\(]+) \\(contains ([^\\)]+)\\)+" - (list _ p1 p2)) - (define ingredients (string-split p1 " ")) - (define allergens (string-split p2 ", ")) - (cons ingredients allergens)] - [_ (error "not shonks" line)]))) + (define-values [lines all-is all-as] + (for/fold ([lines '()] [all-is (set)] [all-as (set)]) ([l (in-list (file->lines fname))]) + (match-define (list _ p1 p2) (regexp-match #px"^([^\\(]+) \\(contains ([^\\)]+)\\)+" l)) + (define is (list->set (string-split p1 " "))) + (define as (list->set (string-split p2 ", "))) + (values (cons (line is as) lines) (set-union all-is is) (set-union all-as as)))) -(module+ test - (require rackunit) - ;; tests here - (displayln "no tests :(")) + (define tainted + (for/hash ([a (in-set all-as)]) + (values a (for/fold ([necessary all-is]) ([l (in-list lines)] + #:when (set-member? (line-as l) a)) + (set-intersect (line-is l) necessary))))) + (data lines all-is all-as tainted)) (module+ main (define input (parse "inputs/21"))