package main import ( "bufio" "fmt" "os" "strconv" "strings" "time" ) func main() { start := time.Now() partOne() duration := time.Since(start) partTwo() duration2 := time.Since(start) fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) } func makeScanner(test bool) *bufio.Scanner { var f *os.File if test { f, _ = os.Open("inputs/testinput") } else { f, _ = os.Open("inputs/input") } reader := bufio.NewReader(f) return bufio.NewScanner(reader) } type display struct { inputs []string outputs []string // mappings from input wires to display pieces top string topleft string topright string center string bottomleft string bottomright string bottom string } func parseLine(line string) display { display := display{ inputs: make([]string, 0), outputs: make([]string, 0), } acc := []byte{} outputs := false for i := 0; i < len(line); i++ { switch line[i] { case 'a', 'b', 'c', 'd', 'e', 'f', 'g': acc = append(acc, line[i]) case ' ': if !outputs { display.inputs = append(display.inputs, string(acc)) acc = []byte{} } else { display.outputs = append(display.outputs, string(acc)) acc = []byte{} } case '|': i++ acc = []byte{} outputs = true } } // and catch the last one display.outputs = append(display.outputs, string(acc)) return display } func removeAll(s, remove string) string { for _, v := range remove { s = strings.ReplaceAll(s, string(v), "") } return s } func timesAppears(s string, list []string) (r int) { for _, v := range list { if strings.Contains(v, s) { r++ } } return } func partOne() { scanner := makeScanner(false) displays := []display{} for scanner.Scan() { displays = append(displays, parseLine(scanner.Text())) } hit := 0 for _, display := range displays { for _, v := range display.outputs { if len(v) == 7 || len(v) == 4 || len(v) == 3 || len(v) == 2 { // 8, 4, 7, 1 hit++ } } } fmt.Println(hit) } func solve(display *display) { mapping := map[int]string{} for _, v := range display.inputs { if len(v) == 2 { mapping[1] = v } if len(v) == 3 { mapping[7] = v } if len(v) == 4 { mapping[4] = v } if len(v) == 7 { mapping[8] = v } } for _, v := range []string{"a", "b", "c", "d", "e", "f", "g"} { if timesAppears(v, display.inputs) == 9 { display.bottomright = v } if timesAppears(v, display.inputs) == 4 { display.bottomleft = v } } display.top = removeAll(mapping[7], mapping[1]) display.bottom = removeAll(mapping[8], mapping[4]+mapping[7]+display.bottomleft) // find 0 for _, v := range display.inputs { if len(v) == 6 { remainder := removeAll(v, display.top+display.bottomleft+display.bottom+mapping[1]) if len(remainder) == 1 { // this is "0", so we found top-left and center display.topleft = remainder display.center = removeAll(mapping[8], v) } } } display.topright = removeAll(mapping[8], display.top+display.topleft+display.center+display.bottomleft+display.bottomright+display.bottom) } func valueFromSolved(d display, unknown string) string { if len(unknown) == 2 { return "1" } if len(unknown) == 3 { return "7" } if len(unknown) == 4 { return "4" } if len(unknown) == 5 { if strings.Contains(unknown, d.topright) && strings.Contains(unknown, d.bottomright) { return "3" } if strings.Contains(unknown, d.topright) && strings.Contains(unknown, d.bottomleft) { return "2" } if strings.Contains(unknown, d.topleft) && strings.Contains(unknown, d.bottomright) { return "5" } } if len(unknown) == 6 { if !strings.Contains(unknown, d.center) { return "0" } if !strings.Contains(unknown, d.bottomleft) { return "9" } if !strings.Contains(unknown, d.topright) { return "6" } } if len(unknown) == 7 { return "8" } panic("uhoh") } func partTwo() { scanner := makeScanner(false) displays := []display{} for scanner.Scan() { displays = append(displays, parseLine(scanner.Text())) } total := 0 for _, v := range displays { solve(&v) sub := "" for _, integer := range v.outputs { sub += valueFromSolved(v, integer) } i, _ := strconv.Atoi(sub) total += i } fmt.Println(total) }