108 lines
3.6 KiB
Racket
108 lines
3.6 KiB
Racket
|
#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"))
|