You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
2.6 KiB
Racket
60 lines
2.6 KiB
Racket
#lang typed/racket
|
|
(require typed/rackunit)
|
|
(provide (all-defined-out))
|
|
(require/typed racket/function ;;bg
|
|
(curryr (-> (-> String String (Listof String)) String (-> String (Listof String)))))
|
|
|
|
(: parse-input-str (-> String (Values String (Listof (Listof String)))))
|
|
(define (parse-input-str input-str)
|
|
(match-define (cons molecule transformation-strings)
|
|
(reverse (string-split input-str "\n")))
|
|
(define transformations
|
|
(filter-not empty?
|
|
(map (curryr string-split " => ")
|
|
transformation-strings)))
|
|
(values molecule transformations))
|
|
|
|
(: transform-molecule* (-> String String String (Listof String)))
|
|
(define (transform-molecule* molecule target-atom replacement-atom)
|
|
(for/list ([pos (in-list (ann (or (regexp-match-positions* (regexp target-atom) molecule) (error 'bg)) (Listof (U #f (Pairof Integer Integer)))))])
|
|
: (Listof String)
|
|
(match-define (cons start finish) (if (pair? pos) pos (error 'bg)))
|
|
(string-append (substring molecule 0 start)
|
|
replacement-atom
|
|
(substring molecule finish (string-length molecule)))))
|
|
|
|
(: q1 (-> String Natural))
|
|
(define (q1 input-str)
|
|
(define-values (molecule transformations) (parse-input-str input-str))
|
|
(length
|
|
(remove-duplicates
|
|
((inst append-map String String String) (λ([target : String] [replacement : String])
|
|
(transform-molecule* molecule target replacement))
|
|
(map (inst first String String) transformations)
|
|
(map (inst second String String String) transformations)))))
|
|
|
|
|
|
(: q2 (-> String Integer))
|
|
(define (q2 input-str)
|
|
(define-values (starting-molecule xforms) (parse-input-str input-str))
|
|
(let loop : Integer ([current-mol starting-molecule][transform-count 0]
|
|
[shuffles 0][xforms xforms])
|
|
(cond
|
|
[(equal? current-mol "e") transform-count]
|
|
[else
|
|
(define-values (xformed-mol last-count)
|
|
(for/fold : (Values String Integer)
|
|
([mol current-mol][count-so-far transform-count])
|
|
([(from to) (in-parallel (map (inst first String String) xforms) (map (inst second String String String) xforms))])
|
|
(values (string-replace mol to from)
|
|
(+ count-so-far (length (regexp-match* to mol))))))
|
|
(if (not (equal? current-mol xformed-mol))
|
|
(loop xformed-mol last-count shuffles xforms)
|
|
(loop starting-molecule 0 (add1 shuffles) (shuffle xforms)))])))
|
|
|
|
(module+ test
|
|
(define input-str (file->string "../day19-input.txt"))
|
|
(check-equal? (q1 input-str) 576)
|
|
(check-equal? (q2 input-str) 207))
|
|
|