package main
import (
"bufio"
"log"
"os"
"regexp"
"sort"
"strings"
)
func main() {
if err := myMain(); err != nil {
log.Println(err)
}
}
func myMain() error {
notes, err := parseInput("input.txt")
if err != nil {
return err
}
log.Println(solveFirst(notes))
log.Println(solveSecond(notes))
return nil
}
var numbers = map[string]int{
"abcefg": 0,
"cf": 1,
"acdeg": 2,
"acdfg": 3,
"bcdf": 4,
"abdfg": 5,
"abdefg": 6,
"acf": 7,
"abcdefg": 8,
"abcdfg": 9,
}
const chars = "abcdefg"
type decodeKey map[rune]rune
func solveSecond(notes Notes) int {
var sum int
for _, n := range notes {
var key = decodeKey{}
key.findKey(n, chars)
sum += key.getValue(n)
}
return sum
}
func (key decodeKey) getValue(note Note) int {
var ret [4]int
for i, out := range note.output {
decoded := strings.Map(func(in rune) rune {
return key[in]
}, out)
decoded = sortString(decoded)
ret[i] = numbers[decoded]
}
return ret[0]*1000 + ret[1]*100 + ret[2]*10 + ret[3]
}
func (key decodeKey) findKey(note Note, in string) bool {
if len(in) == 0 {
if key.checkKey(note) {
return true
}
return false
}
for i := range in {
key[rune(chars[len(key)])] = rune(in[i])
if key.findKey(note, in[:i]+in[i+1:]) {
return true
} else {
delete(key, rune(chars[len(key)-1]))
}
}
return false
}
func (key decodeKey) checkKey(note Note) bool {
for _, digit := range note.signalPatterns {
decoded := strings.Map(func(in rune) rune {
return key[in]
}, digit)
decoded = sortString(decoded)
if _, ok := numbers[decoded]; !ok {
return false
}
}
return true
}
type sortRunes []rune
func (s sortRunes) Less(i, j int) bool {
return s[i] < s[j]
}
func (s sortRunes) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s sortRunes) Len() int {
return len(s)
}
func sortString(s string) string {
r := []rune(s)
sort.Sort(sortRunes(r))
return string(r)
}
func solveFirst(notes Notes) int {
var sum int
for _, note := range notes {
for _, item := range note.output {
switch len(item) {
case 2: sum++
case 4: sum++
case 7: sum++
case 3: sum++
}
}
}
return sum
}
type Note struct {
signalPatterns [10]string
output [4]string
}
type Notes []Note
func parseInput(fileName string) (Notes, error) {
var ret = Notes{}
fd, err := os.Open(fileName)
if err != nil {
return ret, err
}
defer fd.Close()
var line = regexp.MustCompile(`\w+`)
buf := bufio.NewScanner(fd)
for buf.Scan() {
note := Note{}
tmp := line.FindAllString(buf.Text(), -1)
for i := 0; i < 10; i++ {
note.signalPatterns[i] = tmp[i]
}
for i := 0; i < 4; i++ {
note.output[i] = tmp[10+i]
}
ret = append(ret, note)
}
return ret, nil
}