208 lines
4.1 KiB
Go
208 lines
4.1 KiB
Go
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)
|
|
}
|