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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
aoc-racket/typed/day19.rkt

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))