AdventOfCode2021/08/main.go

208 lines
4.1 KiB
Go
Raw Permalink Normal View History

2021-12-08 15:13:49 +00:00
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)
}