diff --git a/19.rkt b/19.rkt index c4fd77a..46940a1 100644 --- a/19.rkt +++ b/19.rkt @@ -3,103 +3,47 @@ (require "scripts/aoc.rkt") ;; solution for day 19 -(struct basic [value] #:transparent) -(struct alias [target] #:transparent) -(struct concat [left right] #:transparent) -(struct orr [left right] #:transparent) -(define (rule-match? rules line [rulenum 0]) - (define rule (hash-ref rules rulenum)) - (cond - [(basic? rule) - (cond - [(zero? (length line)) (values #f '())] - [(char=? (basic-value rule) (first line)) (values #t (list (rest line)))] - [else (values #f '())])] - [(alias? rule) (rule-match? rules line (alias-target rule))] - [(orr? rule) - (define-values [p1 p2] (rule-match? rules line (orr-left rule))) - (define-values [q1 q2] (rule-match? rules line (orr-right rule))) - (cond - [(and p1 q1) (values #t (append p2 q2))] - [p1 (values #t p2)] - [q1 (values #t q2)] - [else (values #f '())])] - [(concat? rule) - (define-values [p1 p2] (rule-match? rules line (concat-left rule))) - (cond - [p1 - (define rst '()) - (define m? #f) - (for ([sub (in-list p2)]) - (define-values [q1 q2] (rule-match? rules sub (concat-right rule))) - (when q1 - (set! rst (append rst q2)) - (set! m? #t))) - (values m? rst)] - [else (values #f '())])])) +;; MEGA CHEATING +(define (run-part defs-in lines) + ;; add the #lang and the top rule + (define defs + (string-append "#lang brag\ntop: r0\n" + ;; replace all the rule numbers N with rN otherwise brag has issues + (regexp-replace* #px"\\d+" defs-in (lambda (x) (format "r~a" x))))) + ;; create a temporary file with the parser contents for brag + (define file (make-temporary-file)) + (call-with-output-file file (lambda (out) (write-string defs out)) #:exists 'truncate) + ;; require it + (define parse (dynamic-require file 'parse)) + ;; yeeeeet + (for/sum ([line (in-list lines)]) + (with-handlers ([exn:fail? (lambda (_) 0)]) ;; catch parse error and just add 0 + (parse line) + 1))) (define (part1 input) (match-define (cons rules lines) input) - (for/sum ([line (in-list lines)]) - (define-values [m? r] (rule-match? rules (string->list line))) - ; (printf "~a: ~a\n" line m?) - (if (and m? (member '() r)) 1 0))) + (run-part rules lines)) (define (part2 input) (match-define (cons rules lines) input) - (define c2 (gensym)) - (hash-set! rules 8 (orr 42 c2)) - (hash-set! rules c2 (concat 42 8)) - - (define c3 (gensym)) - (define c4 (gensym)) - (define c5 (gensym)) - (hash-set! rules 11 (orr c3 c4)) - (hash-set! rules c3 (concat 42 31)) - (hash-set! rules c4 (concat 42 c5)) - (hash-set! rules c5 (concat 11 31)) - - (for/sum ([line (in-list lines)]) - (define-values [m? r] (rule-match? rules (string->list line))) - ; (printf "~a: ~a\n" line m?) - (if (and m? (member '() r)) 1 0))) + ;; replace the lines for 8 and 11 with their replacements, then run it + (run-part + (string-join + (for/list ([line (in-list (string-split rules "\n"))]) + (match line + [(pregexp #px"^8:") "8: 42 | 42 8"] + [(pregexp #px"^11:") "11: 42 31 | 42 11 31"] + [x x])) + "\n") + lines)) ;; parse input file (define (parse fname) - (define sn string->number) - (match-define (list rules-lines input) (string-split (file->string fname) "\n\n")) - (define rules (make-hash)) - (for ([line (in-list (string-split rules-lines "\n"))]) - (match line - [(pregexp #px"^(\\d+): \"(.)\"$" (list _ num char)) - (hash-set! rules (sn num) (basic (string-ref char 0)))] - [(pregexp #px"^(\\d+): (\\d+)$" (list _ num alias-to)) - (hash-set! rules (sn num) (alias (sn alias-to)))] - [(pregexp #px"^(\\d+): (\\d+) (\\d+)$" (list _ num l r)) - (hash-set! rules (sn num) (concat (sn l) (sn r)))] - [(pregexp #px"^(\\d+): (\\d+) (\\d+) (\\d+)$" (list _ num l r r2)) - (define tmp (gensym)) - (hash-set! rules (sn num) (concat (sn l) tmp)) - (hash-set! rules tmp (concat (sn r) (sn r2)))] - [(pregexp #px"^(\\d+): (\\d+) \\| (\\d+)$" (list _ num l r)) - (hash-set! rules (sn num) (orr (sn l) (sn r)))] - [(pregexp #px"^(\\d+): (\\d+) (\\d+) \\| (\\d+) (\\d+)$" (list _ num l1 l2 r1 r2)) - (define ls (gensym)) - (define rs (gensym)) - (hash-set! rules ls (concat (sn l1) (sn l2))) - (hash-set! rules rs (concat (sn r1) (sn r2))) - (hash-set! rules (sn num) (orr ls rs))] - [_ (error "not shonks" line)])) + (match-define (list rules input) (string-split (file->string fname) "\n\n")) (cons rules (string-split input "\n"))) - - -(module+ test - (require rackunit) - ;; tests here - (displayln "no tests :(")) - (module+ main (define input (parse "inputs/19")) (answer 19 1 (time (part1 input)))