day 19: the import solution version

This commit is contained in:
xenia 2020-12-19 01:24:35 -05:00
parent da583918e0
commit 12a57ad8b9
1 changed files with 29 additions and 85 deletions

114
19.rkt
View File

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