(load "../common.scm") ; check if character can close chunk (define (closing? c) (case c (#\) #t) (#\} #t) (#\] #t) (#\> #t) (else #f))) ; check if character can close chunk starting by o (define (is-closed-by? o c) (or (and (char=? o #\<) (char=? c #\>)) (and (char=? o #\{) (char=? c #\})) (and (char=? o #\() (char=? c #\))) (and (char=? o #\[) (char=? c #\])))) ; return character needed to close chunk started by o (define (close o) (case o (#\( #\)) (#\{ #\}) (#\[ #\]) (#\< #\>) (else #f))) ; if given line is corrupt, returns expected character (define (corrupt-char? line) (let loop [(i 0)] (if (< i (string-length line)) (let [(c (string-ref line i))] (if (closing? c) i (let [(close-index (loop (+ i 1)))] (if (number? close-index) (let [(d (string-ref line close-index))] (if (is-closed-by? c d) (loop (+ close-index 1)) d)) close-index)))) #t))) ; compute score after syntax checking all given lines (define (score-illegal-lines lines) (fold-left (lambda (score line) (+ score (case (corrupt-char? line) (#\) 3) (#\] 57) (#\} 1197) (#\> 25137) (else 0)))) 0 lines)) ; returns #t if line is corrupt (define (corrupt? line) (char? (corrupt-char? line))) (define (not-corrupt? line) (not (corrupt? line))) ; returns list of characters needed to autocomplete the given line (define (complete incomplete-line) (let [(stack '())] (string-for-each (lambda (c) (if (closing? c) (set! stack (cdr stack)) (set! stack (cons c stack)))) incomplete-line) (map close stack))) ; returns auto complete score applied to incomplete lines of input (define (score-autocomplete lines) (define (score completion) (fold-left (lambda (s c) (+ (* s 5) (case c (#\) 1) (#\] 2) (#\} 3) (#\> 4)))) 0 completion)) (let [(scores (sort < (map score (map complete (filter not-corrupt? lines)))))] (list-ref scores (div (length scores) 2)))) (call-with-input-file "input" (lambda (file) (let [(lines (get-lines file))] (printf "part 1:~% Illegal lines score = ~a~%" (score-illegal-lines lines)) (printf "part 2:~% Completed lines score = ~a~%" (score-autocomplete lines)))))