Files
2021-12-12 12:29:44 +01:00

103 lines
2.3 KiB
Scheme

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