#lang racket (define data (map string->list (file->lines "day10.txt"))) (define pairs (list (list #\{ #\}) (list #\( #\)) (list #\[ #\]) (list #\< #\>))) (define opening (map first pairs)) (define closing (map second pairs)) (define (go input stack) ; returns the incomplete list OR the first broken bracket if corrupted (if (= 0 (length input)) ; if we've run out of input.. stack ; we've got an incomplete chunk. return the stack (let ([x (first input)] [xs (rest input)]) ; grab the first element of the input (if (member x opening) ; if it is an opening bracket (go xs (cons x stack)) ; push it on the stack and recurse (let* ([y (first stack)] ; otherwise, it's a closing bracket. grab the top of the stack.. [matching (second (assoc y pairs))]) ; and find its matching closing bracket (if (equal? matching x) ; if they match.. (go xs (rest stack)) ; remove it and recurse x)))))) ; if they don't match, return the offending bracket (define part1 (let* ([res (map (λ (x) (go x '())) data)] [bads (filter (λ (x) (not (list? x))) res)] ; filter out the lists - they're the incomplete chunks [costs (list (list #\) 3) (list #\] 57) (list #\} 1197) (list #\> 25137))] [points (map (λ (x) (second (assoc x costs))) bads)] [total (apply + points)]) total)) part1 ; PART 2 (define (complete input stack) ; find the necessary closing brackets to complete the chunk (if (= 0 (length input)) stack (let* ([x (first input)] [matching (second (assoc x pairs))]) (complete (rest input) (cons matching stack))))) (define (score chunk) (let ([costs (list (list #\) 1) (list #\] 2) (list #\} 3) (list #\> 4))]) (foldl (λ (x acc) (+ (second (assoc x costs)) (* 5 acc))) 0 chunk))) (define part2 (let* ([res (map (λ (x) (go x '())) data)] [rev (reverse res)] ; reverse so we can use `first` & `cons` [incompletes (filter (λ (x) (list? x)) res)] ; filter out the lists - they're the incomplete chunks [completing (map reverse (map (λ (x) (complete x '())) incompletes))] ; un-reverse it [scores (map score completing)] [sorted (sort scores <)]) (list-ref sorted (/ (- (length sorted) 1) 2)))) ; find the median scoring chunk part2