In addition to the garbled display output, the problem input also contains a list of all ten garbled digits. With a little bit of logic it's possible to determine which digit is represented by which garbled signals, and from there return the sum of the displayed values.
$ cat 08b.rkt #lang racket (require (prefix-in aoc08: "08a.rkt") ) (define (aoc08b . args) ; Decode the garbled signals, and return the sum of the displayed ; numbers. If no display i-o is given, use the contest problem ; input; otherwise assume the argument is the string representation ; of a problem input. (apply + (map (lambda (l) (decode-display l)) (apply aoc08:read-input args)))) (define (decode-display display-status) ; Return the value displayed in the given display status line. (let ((dssm (get-digit-signal-set-mapping (car display-status)))) (foldl (lambda (ss s) (+ (dssm 'get ss) (* 10 s))) 0 (cadr display-status)))) (define (get-digit-signal-set-mapping digit-signal-sets) ; Return a mapping between digits and signal sets derived from ; the given list of signal sets. (define dssm (new-digit-signal-set-mapping)) (define (select-segment-set p) ; Return the segment set satisfying p; there is assumed to be ; exactly one such segment set. (let ((signal-set (filter p digit-signal-sets))) (case (length signal-set) ((0) (error "can't find a satisfactory segment set")) ((1) (let ((ss (car signal-set))) (set! digit-signal-sets (remove ss digit-signal-sets)) ss)) (else (error "found more than one satisfactory segment set"))))) (define (get-segments-by-size n) ; Return the segment set having the given size. (select-segment-set (lambda (ss) (= (length ss) n)))) (define (get-segments-by-difference-size ss-size d d-size) ; Return the segment set with the given size and (select-segment-set (lambda (ss) (and (= (length ss) ss-size) (difference-size ss d d-size))))) (define (difference-size s-set d d-size) ; Return #t iff the cardinality of the difference between the ; given signal set and the signal set for the given digit is ; equal to the given size. (= d-size (foldl (lambda (s c) (- c (if (member s s-set) 1 0))) (length s-set) (dssm 'get d)))) ; 1, 4, 7 and 8 have unique segment counts among all the digits. (for-each (lambda (p) (dssm 'put (car p) (get-segments-by-size (cdr p)))) '((1 . 2) (4 . 4) (7 . 3) (8 . 7))) ; 3 is the only 5-segment digit with 3 segments not in 1. (dssm 'put 3 (get-segments-by-difference-size 5 1 3)) ; Without 3, 2 is the only 5-segment digit with 3 segments not in 4. (dssm 'put 2 (get-segments-by-difference-size 5 4 3)) ; The only 5-digit segment left is 5. (dssm 'put 5 (get-segments-by-size 5)) ; There are only six-segment digits left: 0 6 9. ; 9 is the only six-segment digit with one segment not in 3. (dssm 'put 9 (get-segments-by-difference-size 6 3 1)) ; Without 9, 0 is the only six-segment digit with 2 segments not in 5 (dssm 'put 0 (get-segments-by-difference-size 6 5 2)) ; 6 is the only six-segment digit left. (dssm 'put 6 (get-segments-by-size 6)) dssm) (define (new-digit-signal-set-mapping) (let ((d2ss (make-hash)) (ss2d (make-hash)) (oops (lambda args (apply raise-user-error (cons 'digit-signal-set-mapping args))))) (lambda (cmd . args) (case (list 'quote cmd) (('get ) (unless (= (length args) 1) (oops "get expects 1 argument, got ~a" (length args))) (let ((a (car args))) (cond ((number? a) (hash-ref d2ss a)) ((list? a) (hash-ref ss2d (sort a char<?))) (#t (oops "get expects a value of type int or list"))))) (('put) (unless (= (length args) 2) (oops "put expects 2 arguments, got ~a" (length args))) (let ((d (car args)) (ss (sort (cadr args) char<?))) (hash-set! d2ss d ss) (hash-set! ss2d ss d))) (else (oops "Don't recognize ~a as a command" cmd)))))) (module+ main (aoc08b) ) (module+ test (require rackunit) (define dssm (get-digit-signal-set-mapping (caar (aoc08:read-input "gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce")))) (for-each (lambda (p) (check-equal? (dssm 'get (car p)) (cdr p))) '((0 . (#\b #\c #\d #\e #\f #\g)) (1 . (#\f #\g)) (2 . (#\a #\b #\c #\d #\f)) (3 . (#\a #\b #\c #\f #\g)) (4 . (#\a #\e #\f #\g)) (5 . (#\a #\b #\c #\e #\g)) (6 . (#\a #\b #\c #\d #\e #\g)) (7 . (#\c #\f #\g)) (8 . (#\a #\b #\c #\d #\e #\f #\g)) (9 . (#\a #\b #\c #\e #\f #\g)) )) (for-each (lambda (p) (check-equal? (decode-display (car (aoc08:read-input (car p)))) (cdr p))) '(("be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe" . 8394) ("edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc" . 9781) ("fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg" . 1197) ("fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb" . 9361) ("aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea" . 4873) ("fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb" . 8418) ("dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe" . 4548) ("bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef" . 1625) ("egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb" . 8717) ("gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce" . 4315))) (check-equal? (aoc08b aoc08:example-input) 61229) (check-equal? (aoc08b) 1043697) ) $ raco test 08b.rkt raco test: (submod "08b.rkt" test) 22 tests passed $