diff --git a/16.rkt b/16.rkt index d9fd096..238fa53 100644 --- a/16.rkt +++ b/16.rkt @@ -4,78 +4,58 @@ ;; solution for day 16 -(struct note [name rule0 rule1] #:transparent) +(struct note [name test] #:transparent) -(define (invalid? notes val) - (not - (for/or ([n (in-list notes)]) - (match-define (note name (cons a b) (cons c d)) n) - (or (and (>= val a) (<= val b)) (and (>= val c) (<= val d)))))) +(define (valid? notes val) + (ormap #{(note-test %) val} notes)) (define (part1 input) (match-define (list notes yours others) input) - (for/sum ([tick (in-list others)]) - (for/sum ([val (in-list tick)] #:when (invalid? notes val)) val))) + (for*/sum ([tick (in-list others)] [val (in-list tick)] #:unless (valid? notes val)) + val)) (define (part2 input) (match-define (list notes yours others) input) - (define (ticket-valid? tick) - (not (for/or ([val (in-list tick)]) (invalid? notes val)))) - (define valid-tickets (filter ticket-valid? others)) + (define valid-tickets (filter #{andmap #{valid? notes %} %} others)) - (define mapping (make-hash)) - - (for ([idx (in-range (length yours))]) - (define decided-note (mutable-set)) - (for ([cand-note (in-list notes)]) - (define shonks - (for/and ([tick (in-list valid-tickets)]) - (not (invalid? (list cand-note) (list-ref tick idx))))) - (when shonks - (set-add! decided-note (note-name cand-note)))) - (when (set-empty? decided-note) (error "couldn't decide...")) - (hash-set! mapping idx decided-note)) - - ; (displayln mapping) + (define mapping + (for/vector ([idx (in-range (length yours))]) + (define matching-notes + (for/mutable-set ([cand-note (in-list notes)] + #:when (andmap #{valid? (list cand-note) (list-ref % idx)} valid-tickets)) + (note-name cand-note))) + (when (set-empty? matching-notes) (error "couldn't decide...")) + matching-notes)) (let loop () - (for ([(k v) (in-hash mapping)]) - (when (= 1 (set-count v)) - (define fst (set-first v)) - (for ([k2 (in-list (hash-keys mapping))] #:unless (= k2 k)) - (set-remove! (hash-ref mapping k2) fst)))) - (when (for/or ([(k v) (in-hash mapping)]) - (> (set-count v) 1)) - (displayln "looping") + (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))) - (displayln mapping) - (for/product ([val (in-list yours)] [idx (in-naturals)]) - (define n (set-first (hash-ref mapping idx))) - (displayln n) - (if (string-contains? n "departure") - (begin (displayln val) val) + (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) - (match-define (list notes yours others) (string-split (file->string fname) "\n\n")) (define sn string->number) - (define pnotes (for/list ([line (in-list (string-split notes "\n"))]) - (match line - [(pregexp #px"^([^:]+): (\\d+)\\-(\\d+) or (\\d+)-(\\d+)$" - (list _ name a b c d)) - (note name (cons (sn a) (sn b)) (cons (sn c) (sn d)))]))) - (define pyours (map sn (string-split (second (string-split yours "\n")) ","))) - (define pothers (for/list ([line (in-list (rest (string-split others "\n")))]) - (map sn (string-split line ",")))) - - (list pnotes pyours pothers)) - -(module+ test - (require rackunit) - ;; tests here - (displayln "no tests :(")) + (match-define (list notes-in yours-in others-in) (string-split (file->string fname) "\n\n")) + (list (for/list ([line (in-list (string-split notes-in "\n"))]) + (match line + [(pregexp #px"^([^:]+): (\\d+)\\-(\\d+) or (\\d+)-(\\d+)$" + (list _ name (app sn a) (app sn b) (app sn c) (app sn d))) + (note name #{or (<= a % b) (<= c % d)})])) + (map sn (string-split (second (string-split yours-in "\n")) ",")) + (for/list ([line (in-list (rest (string-split others-in "\n")))]) + (map sn (string-split line ","))))) (module+ main (define input (parse "inputs/16"))