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" 

fancyapp) 



(struct segment (signalpattern output) #:transparent) 



(define (parse lines) 

(for/list ([line (inlist lines)]) 

(matchdefine `(,pat ,out) (stringsplit line "")) 

(segment (map (compose (apply set _) string>list) 

(stringsplit pat)) 

(map (compose (apply set _) string>list) 

(stringsplit out))))) 



(define ((determinedigit patterns) seg) 

(define (withlength len) 

(for/list ([pattern (inlist patterns)] 

#:when (= (setcount pattern) len)) 

pattern)) 



(define one (first (withlength 2))) 

(define four (first (withlength 4))) 

(define seven (first (withlength 3))) 

(define eight (first (withlength 7))) 

; fives are 2, 3, 5 

; 2 intersect 3 intersect 5 = adg 

(define adg (apply setintersect (withlength 5))) 

; adg union 1 = 3 

(define three (setunion adg one)) 

; adg union 4 = 9 

(define nine (setunion adg four)) 

; sixes are 0, 6, 9 

; 6 intersect 9 intersect 0 = agf 

(define agf (apply setintersect (withlength 6))) 

; f = agf minus adg 

(define f (setsubtract agf adg)) 

; agf union adg = adgf, adgf union 4 = abcdgf, e = 8 minus abcdgf 

(define e (setsubtract eight (setunion agf adg four))) 

; two = three minus f union e 

(define two (setunion (setsubtract three f) e)) 

; cf = 4 intersect 7, c = cf minus f 

(define c (setsubtract (setintersect four seven) f)) 

; six = 8 minus c 

(define six (setsubtract eight c)) 

; five = 8 minus c minus e 

(define five (setsubtract eight c e)) 

; zero = 8 minus adg union agf 

(define zero (setunion (setsubtract 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 (inlist segs)] 

[out (inlist (segmentoutput seg))] 

#:when (or (= (setcount out) 2) 

(= (setcount out) 3) 

(= (setcount out) 4) 

(= (setcount out) 7))) 

1)) 



(define (day8b segs) 

(for/sum ([seg (inlist segs)]) 

(matchdefine (segment pats outs) seg) 

(string>number (apply string (map (determinedigit pats) outs))))) 



(module+ main 

(callwithinputfile "data/day8.txt" 

(λ (prt) 

(define segs (parse (port>lines prt))) 

(answer 8 1 (day8a segs)) 

(answer 8 2 (day8b segs)))))


