Given a set of strings, where each string is a sequence of nested groups delimited by one of four bracketing characters ('(', '[', '{', '<' and associated closing characters), find the left-most mismatched group (which may not exist). Assign the mismatched closing bracket a score, and return the sum of the scores of all mismatched brackets.
$ cat 10a.rkt #lang racket (provide example-input read-input ) (require "./aoc.rkt") (define (aoc10a . args) ; Return the nav-sys error score for the first half of the ; tenth AoC '21 problem. If no argument is given, use the ; contest problem input; otherwise assume the argument is ; the string representation of a problem input. (total-error-score (apply read-input args))) (define line-error-score ; Return the error score for the given nav-system line. (let* ((error-scores (make-hash '((#\) . 3) (#\] . 57) (#\} . 1197) (#\> . 25137)))) (group-close (make-hash '((#\( . #\)) (#\[ . #\]) (#\{ . #\}) (#\< . #\>)))) (push (lambda (s e) (cons e s))) (pop cdr) (top car) (is-group-open? (lambda (c) (member c '(#\( #\[ #\{ #\<)))) (closes-group? (lambda (g c) (and (not (null? g)) (char=? (hash-ref group-close (top g)) c))))) (lambda (nav-sys-line) (call-with-current-continuation (lambda (k) (foldl (lambda (e open-groups) (cond ((is-group-open? e) (push open-groups e)) ((closes-group? open-groups e) (pop open-groups)) (#t (k (hash-ref error-scores e))))) '() nav-sys-line) 0))))) (define (read-input . inp) ; Return the navigation subsystem described by the given ; input. If no input is given, use the contest problem ; input; otherwise the argument is taken to be the string ; representation of input. (map string->list (flatten (car (aoc-read-input (if (null? inp) 10 (car inp))))))) (define (total-error-score nav-sys) ; Return the total error score for the given nav system. (apply + (map line-error-score nav-sys))) (module+ main (aoc10a) ) (define example-input (string-join '("[({(<(())[]>[[{[]{<()<>>" "[(()[<>])]({[<{<<[]>>(" "{([(<{}[<>[]}>{[]{[(<()>" "(((({<>}<{<{<>}{[]{[]{}" "[[<[([]))<([[{}[[()]]]" "[{[{({}]{}}([{[{{{}}([]" "{<[[]]>}<{[{[{[]{()[[[]" "[<(<(<(<{}))><([]([]()" "<{([([[(<>()){}]>(<<{{" "<{([{{}}[<[[[<>{}]]]>[]]" ) "\n")) (define example-output 26397) (module+ test (require rackunit) (check-equal? (line-error-score (read-input "")) 0) (for-each (lambda (p) (check-equal? (line-error-score (car (read-input (car p)))) (cadr p))) '(("(" 0) ("()" 0) (")" 3) ("[" 0) ("[]" 0) ("]" 57) ("{" 0) ("{}" 0) ("}" 1197) ("<" 0) ("<>" 0) (">" 25137) ("{([(<{}[<>[]}>{[]{[(<()>" 1197) ("[[<[([]))<([[{}[[()]]]" 3) ("[{[{({}]{}}([{[{{{}}([]" 57) ("[<(<(<(<{}))><([]([]()" 3) ("<{([([[(<>()){}]>(<<{{" 25137))) (check-equal? (total-error-score (read-input example-input)) example-output) (check-equal? (aoc10a example-input) example-output) ) $ raco test 10a.rkt raco test: (submod "10a.rkt" test) 20 tests passed $