day 16: implement bipartite-matching solution

This commit is contained in:
xenia 2020-12-16 01:18:43 -05:00
parent e2468a6e71
commit dc4fb90f08
1 changed files with 9 additions and 26 deletions

35
16.rkt
View File

@ -17,34 +17,17 @@
(define (part2 input) (define (part2 input)
(match-define (list notes yours others) input) (match-define (list notes yours others) input)
(define valid-tickets (filter #{andmap #{valid? notes %} %} others)) (define valid-tickets (filter #{andmap #{valid? notes %} %} others))
(define (match? idx cand-note)
(andmap #{valid? (list cand-note) (list-ref % idx)} valid-tickets))
(define mapping (define G (undirected-graph
(for/vector ([idx (in-range (length yours))]) (for*/list ([idx (in-range (length yours))] [cand-note (in-list notes)]
(define matching-notes #:when (match? idx cand-note))
(for/mutable-set ([cand-note (in-list notes)] (list idx (note-name cand-note)))))
#:when (andmap #{valid? (list cand-note) (list-ref % idx)} valid-tickets)) (for/product ([elem (in-list (maximum-bipartite-matching G))]
(note-name cand-note))) #:when (string-contains? (second elem) "departure"))
(when (set-empty? matching-notes) (error "couldn't decide...")) (list-ref yours (first elem))))
matching-notes))
(let loop ()
(define has-conflicts #f)
(for ([v (in-vector mapping)] [k (in-naturals)])
(cond
[(= 1 (set-count v))
(define fst (set-first v))
(for ([v2 (in-vector mapping)] [k2 (in-naturals)] #:unless (= k2 k))
(set-remove! v2 fst))]
[else (set! has-conflicts #t)]))
(when has-conflicts
(loop)))
(for/product ([val (in-list yours)] [name-set (in-vector mapping)])
(if (string-contains? (set-first name-set) "departure")
val
1)))
;; parse input file
(define (parse fname) (define (parse fname)
(define sn string->number) (define sn string->number)
(match-define (list notes-in yours-in others-in) (string-split (file->string fname) "\n\n")) (match-define (list notes-in yours-in others-in) (string-split (file->string fname) "\n\n"))