#lang curly-fn racket (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 '())])])) (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))) (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))) ;; 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)])) (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))) (answer 19 2 (time (part2 input))) (displayln "meow"))