advent-of-code/2021/08/second.go

143 lines
3.1 KiB
Go

package main
import (
"bufio"
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
)
func sortStrings(strs []string) {
for i, v := range strs {
s := strings.Split(v, "")
sort.Strings(s)
strs[i] = strings.Join(s, "")
}
}
func deduceSix(one string, zns []string) string { // zns == zero, nine and six
for _, v := range zns {
for _, c := range one {
if !strings.Contains(v, string(c)) {
return v
}
}
}
log.Fatalf("deduce(%+v, %+v) failed!", one, zns)
return ""
}
func deduceTwoThreeFive(ttf []string, topRight, bottomRight byte) (two string, three string, five string) {
for _, s := range ttf {
if !strings.Contains(s, string(topRight)) {
five = s
} else if !strings.Contains(s, string(bottomRight)) {
two = s
} else {
three = s
}
}
return
}
func deduceRight(one, six string) (byte, byte) {
if strings.Contains(six, string(one[0])) {
return one[1], one[0]
} else {
return one[0], one[1]
}
}
func deduceBottomLeft(one, two, five string) byte {
for _, ch := range two {
s := string(ch)
if strings.Contains(one, s) || strings.Contains(five, s) {
continue
}
return s[0]
}
log.Fatalf("deduceBottomLeft(%+v, %+v, %+v) failed!", one, two, five)
return 0 // cannot happen
}
func deduceZeroNine(zsn []string, six string, bottomLeft byte) (zero string, nine string) {
for _, s := range zsn {
if s == six {
continue
}
if strings.Contains(s, string(bottomLeft)) {
zero = s
} else {
nine = s
}
}
return
}
func main() {
score := 0
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
inputs := strings.Split(s.Text(), " | ")
hints := strings.Split(inputs[0], " ")
outputs := strings.Split(inputs[1], " ")
sort.Slice(hints, func(i, j int) bool {
return len(hints[i]) < len(hints[j])
})
sortStrings(hints)
sortStrings(outputs)
// some digits are straightforward :
one := hints[0]
seven := hints[1]
four := hints[2]
eight := hints[9]
// We can deduce number 6 by being in len 6 and missing a component from 1
six := deduceSix(one, hints[6:9])
// the right segments can be deduced from the one in 1 that is in the 6
topRight, bottomRight := deduceRight(one, six)
// We can deduce numbers two, three and five from the right segments
two, three, five := deduceTwoThreeFive(hints[3:6], topRight, bottomRight)
// We can deduce the bottom left segment from 1 2 and 5
bottomLeft := deduceBottomLeft(one, two, five)
// We can deduce numbers 0 and 9 from the bottom left segment and the fact we already know 6
zero, nine := deduceZeroNine(hints[6:9], six, bottomLeft)
key := make([]byte, 4)
for i, s := range outputs {
switch s {
case zero:
key[i] = '0'
case one:
key[i] = '1'
case two:
key[i] = '2'
case three:
key[i] = '3'
case four:
key[i] = '4'
case five:
key[i] = '5'
case six:
key[i] = '6'
case seven:
key[i] = '7'
case eight:
key[i] = '8'
case nine:
key[i] = '9'
default:
fmt.Println(zero, one, two, three, four, five, six, seven, eight, nine)
log.Fatalf("Did not find %+v", s)
}
}
v, _ := strconv.Atoi(string(key))
score += v
}
fmt.Println(score)
}