You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.6 KiB
80 lines
2.6 KiB
#lang racket |
|
(require "lib/common.rkt" |
|
fancy-app) |
|
|
|
(struct segment (signal-pattern output) #:transparent) |
|
|
|
(define (parse lines) |
|
(for/list ([line (in-list lines)]) |
|
(match-define `(,pat ,out) (string-split line "|")) |
|
(segment (map (compose (apply set _) string->list) |
|
(string-split pat)) |
|
(map (compose (apply set _) string->list) |
|
(string-split out))))) |
|
|
|
(define ((determine-digit patterns) seg) |
|
(define (with-length len) |
|
(for/list ([pattern (in-list patterns)] |
|
#:when (= (set-count pattern) len)) |
|
pattern)) |
|
|
|
(define one (first (with-length 2))) |
|
(define four (first (with-length 4))) |
|
(define seven (first (with-length 3))) |
|
(define eight (first (with-length 7))) |
|
; fives are 2, 3, 5 |
|
; 2 intersect 3 intersect 5 = adg |
|
(define adg (apply set-intersect (with-length 5))) |
|
; adg union 1 = 3 |
|
(define three (set-union adg one)) |
|
; adg union 4 = 9 |
|
(define nine (set-union adg four)) |
|
; sixes are 0, 6, 9 |
|
; 6 intersect 9 intersect 0 = agf |
|
(define agf (apply set-intersect (with-length 6))) |
|
; f = agf minus adg |
|
(define f (set-subtract agf adg)) |
|
; agf union adg = adgf, adgf union 4 = abcdgf, e = 8 minus abcdgf |
|
(define e (set-subtract eight (set-union agf adg four))) |
|
; two = three minus f union e |
|
(define two (set-union (set-subtract three f) e)) |
|
; cf = 4 intersect 7, c = cf minus f |
|
(define c (set-subtract (set-intersect four seven) f)) |
|
; six = 8 minus c |
|
(define six (set-subtract eight c)) |
|
; five = 8 minus c minus e |
|
(define five (set-subtract eight c e)) |
|
; zero = 8 minus adg union agf |
|
(define zero (set-union (set-subtract eight adg) agf)) |
|
|
|
(cond [(set=? seg zero) #\0] |
|
[(set=? seg one) #\1] |
|
[(set=? seg two) #\2] |
|
[(set=? seg three) #\3] |
|
[(set=? seg four) #\4] |
|
[(set=? seg five) #\5] |
|
[(set=? seg six) #\6] |
|
[(set=? seg seven) #\7] |
|
[(set=? seg eight) #\8] |
|
[(set=? seg nine) #\9])) |
|
|
|
(define (day8a segs) |
|
(for*/sum ([seg (in-list segs)] |
|
[out (in-list (segment-output seg))] |
|
#:when (or (= (set-count out) 2) |
|
(= (set-count out) 3) |
|
(= (set-count out) 4) |
|
(= (set-count out) 7))) |
|
1)) |
|
|
|
(define (day8b segs) |
|
(for/sum ([seg (in-list segs)]) |
|
(match-define (segment pats outs) seg) |
|
(string->number (apply string (map (determine-digit pats) outs))))) |
|
|
|
(module+ main |
|
(call-with-input-file "data/day8.txt" |
|
(λ (prt) |
|
(define segs (parse (port->lines prt))) |
|
(answer 8 1 (day8a segs)) |
|
(answer 8 2 (day8b segs)))))
|
|
|