196 lines
3.3 KiB
Go
196 lines
3.3 KiB
Go
package eight
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
one = 2
|
|
four = 4
|
|
seven = 3
|
|
eight = 7
|
|
)
|
|
|
|
type output struct {
|
|
signals []string
|
|
outputs []string
|
|
}
|
|
|
|
type display struct {
|
|
outputs []output
|
|
}
|
|
|
|
func (d *display) load(filename string) error {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
o := output{}
|
|
|
|
insOuts := strings.Split(scanner.Text(), " | ")
|
|
|
|
o.signals = strings.Split(insOuts[0], " ")
|
|
o.outputs = strings.Split(insOuts[1], " ")
|
|
|
|
d.outputs = append(d.outputs, o)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *display) uniqueOuputs() int {
|
|
count := 0
|
|
for _, o := range d.outputs {
|
|
for _, s := range o.outputs {
|
|
switch len(s) {
|
|
case one, four, seven, eight:
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
|
|
return count
|
|
}
|
|
|
|
func (o *output) decode() (value int) {
|
|
decoded := make(map[string]int, 10)
|
|
twoThreeFive := []string{}
|
|
zeroSixNine := []string{}
|
|
|
|
sortedSignals := []string{}
|
|
for _, s := range o.signals {
|
|
segments := sort.StringSlice(strings.Split(s, ""))
|
|
sort.Sort(segments)
|
|
sortedSignals = append(sortedSignals, strings.Join(segments, ""))
|
|
}
|
|
|
|
// Find known digits
|
|
for _, s := range sortedSignals {
|
|
switch len(s) {
|
|
case one:
|
|
decoded[s] = 1
|
|
case four:
|
|
decoded[s] = 4
|
|
case seven:
|
|
decoded[s] = 7
|
|
case eight:
|
|
decoded[s] = 8
|
|
case 5:
|
|
twoThreeFive = append(twoThreeFive, s)
|
|
case 6:
|
|
zeroSixNine = append(zeroSixNine, s)
|
|
}
|
|
}
|
|
|
|
// Decode twoThreeFive
|
|
twoFive := []string{}
|
|
// Find 3 string
|
|
for s, v := range decoded {
|
|
if v == 1 {
|
|
for _, v := range twoThreeFive {
|
|
sharedSegments := 0
|
|
for _, segment := range s {
|
|
if strings.Contains(v, string(segment)) {
|
|
sharedSegments++
|
|
}
|
|
}
|
|
if sharedSegments == 2 {
|
|
decoded[v] = 3
|
|
} else {
|
|
twoFive = append(twoFive, v)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Find 5 and 2 string
|
|
for s, v := range decoded {
|
|
if v == 4 {
|
|
for _, v := range twoFive {
|
|
sharedSegments := 0
|
|
for _, segment := range s {
|
|
if strings.Contains(v, string(segment)) {
|
|
sharedSegments++
|
|
}
|
|
}
|
|
if sharedSegments == 3 {
|
|
decoded[v] = 5
|
|
} else {
|
|
decoded[v] = 2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Decode zeroSixNine
|
|
// Find 0 string
|
|
sixNine := []string{}
|
|
for s, v := range decoded {
|
|
if v == 5 {
|
|
for _, v := range zeroSixNine {
|
|
sharedSegments := 0
|
|
for _, segment := range s {
|
|
if strings.Contains(v, string(segment)) {
|
|
sharedSegments++
|
|
}
|
|
}
|
|
if sharedSegments != 5 {
|
|
decoded[v] = 0
|
|
} else {
|
|
sixNine = append(sixNine, v)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Find the 9 and 6 strings
|
|
for s, v := range decoded {
|
|
if v == 1 {
|
|
for _, v := range sixNine {
|
|
sharedSegments := 0
|
|
for _, segment := range s {
|
|
if strings.Contains(v, string(segment)) {
|
|
sharedSegments++
|
|
}
|
|
}
|
|
if sharedSegments == 2 {
|
|
decoded[v] = 9
|
|
} else {
|
|
decoded[v] = 6
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for i, signal := range o.outputs {
|
|
scale := 1
|
|
switch i {
|
|
case 0:
|
|
scale = 1000
|
|
case 1:
|
|
scale = 100
|
|
case 2:
|
|
scale = 10
|
|
}
|
|
|
|
segments := sort.StringSlice(strings.Split(signal, ""))
|
|
sort.Sort(segments)
|
|
sortedSignal := strings.Join(segments, "")
|
|
|
|
value += scale * decoded[sortedSignal]
|
|
}
|
|
|
|
return value
|
|
}
|
|
|
|
func (d *display) outputSum() (sum int) {
|
|
for _, o := range d.outputs {
|
|
sum += o.decode()
|
|
}
|
|
return sum
|
|
}
|