2022-02-19 17:23:06 +02:00
|
|
|
package d8
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"sort"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
func difference(a []string, b []string) []string {
|
|
|
|
needle := a
|
|
|
|
haystack := b
|
|
|
|
|
|
|
|
if len(a) > len(b) {
|
|
|
|
needle = b
|
|
|
|
haystack = a
|
|
|
|
}
|
|
|
|
|
|
|
|
mb := make(map[string]struct{}, len(needle))
|
|
|
|
for _, x := range needle {
|
|
|
|
mb[x] = struct{}{}
|
|
|
|
}
|
|
|
|
var diff []string
|
|
|
|
for _, x := range haystack {
|
|
|
|
if _, found := mb[x]; !found {
|
|
|
|
diff = append(diff, x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return diff
|
|
|
|
}
|
|
|
|
|
|
|
|
func merge(a []string, b []string) []string {
|
|
|
|
return append(append([]string{}, a...), b...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func findSegment(digits [][]string, part []string) string {
|
|
|
|
for _, digit := range digits {
|
|
|
|
diff := difference(digit, part)
|
|
|
|
|
|
|
|
if len(digit) > len(part) && len(diff) == 1 {
|
|
|
|
return diff[0]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Fatal("can't find segment")
|
|
|
|
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// aaaa
|
|
|
|
// b c
|
|
|
|
// b c
|
|
|
|
// dddd
|
|
|
|
// e f
|
|
|
|
// e f
|
|
|
|
// gggg
|
|
|
|
//
|
|
|
|
// a: 0, c: 1, f: 2, g: 3, e: 4, b: 5, d: 6
|
|
|
|
func findDisplay(digitsAsString string) []string {
|
|
|
|
display := make([]string, 7)
|
|
|
|
|
|
|
|
digits := [][]string{}
|
|
|
|
splitted := strings.Split(digitsAsString, " ")
|
|
|
|
sort.Slice(splitted, func(i, j int) bool { return len(splitted[i]) < len(splitted[j]) })
|
|
|
|
for _, digit := range splitted {
|
|
|
|
digits = append(digits, strings.Split(digit, ""))
|
|
|
|
}
|
|
|
|
|
|
|
|
// a
|
|
|
|
display[0] = findSegment(digits, digits[0])
|
|
|
|
// g
|
|
|
|
display[3] = findSegment(digits, merge(digits[2], []string{display[0]}))
|
|
|
|
// e
|
|
|
|
display[4] = findSegment(digits, merge(digits[2], []string{display[0], display[3]}))
|
|
|
|
// d
|
|
|
|
display[6] = findSegment(digits, merge(digits[1], []string{display[3]}))
|
|
|
|
// b
|
|
|
|
display[5] = findSegment(digits, merge(digits[1], []string{display[3], display[4], display[6]}))
|
|
|
|
// f
|
|
|
|
display[2] = findSegment(digits, []string{display[0], display[3], display[4], display[5], display[6]})
|
|
|
|
// c
|
|
|
|
display[1] = findSegment(digits, []string{display[0], display[2], display[3], display[4], display[5], display[6]})
|
|
|
|
|
|
|
|
return display
|
|
|
|
}
|
|
|
|
|
|
|
|
func isOne(digit []string, display []string) bool {
|
|
|
|
return len(digit) == 2
|
|
|
|
}
|
|
|
|
|
|
|
|
func isTwo(digit []string, display []string) bool {
|
|
|
|
|
|
|
|
if len(digit) != 5 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
two := strings.Join([]string{display[0], display[1], display[3], display[4], display[6]}, "")
|
|
|
|
|
|
|
|
for _, segment := range digit {
|
|
|
|
if !strings.Contains(two, segment) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func isThree(digit []string, display []string) bool {
|
|
|
|
|
|
|
|
if len(digit) != 5 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
three := strings.Join([]string{display[0], display[1], display[2], display[3], display[6]}, "")
|
|
|
|
|
|
|
|
for _, segment := range digit {
|
|
|
|
if !strings.Contains(three, segment) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func isFour(digit []string, display []string) bool {
|
|
|
|
return len(digit) == 4
|
|
|
|
}
|
|
|
|
|
|
|
|
func isFive(digit []string, display []string) bool {
|
|
|
|
|
|
|
|
if len(digit) != 5 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
three := strings.Join([]string{display[0], display[2], display[3], display[5], display[6]}, "")
|
|
|
|
|
|
|
|
for _, segment := range digit {
|
|
|
|
if !strings.Contains(three, segment) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func isSix(digit []string, display []string) bool {
|
|
|
|
|
|
|
|
if len(digit) != 6 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
three := strings.Join([]string{display[0], display[2], display[3], display[4], display[5], display[6]}, "")
|
|
|
|
|
|
|
|
for _, segment := range digit {
|
|
|
|
if !strings.Contains(three, segment) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func isSeven(digit []string, display []string) bool {
|
|
|
|
return len(digit) == 3
|
|
|
|
}
|
|
|
|
|
|
|
|
func isEight(digit []string, display []string) bool {
|
|
|
|
return len(digit) == 7
|
|
|
|
}
|
|
|
|
|
|
|
|
func isNine(digit []string, display []string) bool {
|
|
|
|
|
|
|
|
if len(digit) != 6 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
three := strings.Join([]string{display[0], display[1], display[2], display[3], display[5], display[6]}, "")
|
|
|
|
|
|
|
|
for _, segment := range digit {
|
|
|
|
if !strings.Contains(three, segment) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func isZero(digit []string, display []string) bool {
|
|
|
|
|
|
|
|
if len(digit) != 6 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
three := strings.Join([]string{display[0], display[1], display[2], display[3], display[4], display[5]}, "")
|
|
|
|
|
|
|
|
for _, segment := range digit {
|
|
|
|
if !strings.Contains(three, segment) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func digitToNumber(digit []string, display []string) int {
|
|
|
|
numberMap := map[int]func([]string, []string) bool{
|
|
|
|
0: isZero,
|
|
|
|
1: isOne,
|
|
|
|
2: isTwo,
|
|
|
|
3: isThree,
|
|
|
|
4: isFour,
|
|
|
|
5: isFive,
|
|
|
|
6: isSix,
|
|
|
|
7: isSeven,
|
|
|
|
8: isEight,
|
|
|
|
9: isNine,
|
|
|
|
}
|
|
|
|
|
|
|
|
for number, f := range numberMap {
|
|
|
|
if f(digit, display) {
|
|
|
|
return number
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Fatal("wrong digit", digit, display)
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func findCode(digitsAsString string, display []string) int {
|
|
|
|
numbers := []string{}
|
|
|
|
for _, digit := range strings.Split(digitsAsString, " ") {
|
|
|
|
numbers = append(numbers, strconv.Itoa(digitToNumber(strings.Split(digit, ""), display)))
|
|
|
|
}
|
|
|
|
asInt, _ := strconv.Atoi(strings.Join(numbers, ""))
|
|
|
|
|
|
|
|
return asInt
|
|
|
|
}
|
|
|
|
|
2022-02-22 01:55:11 +02:00
|
|
|
// TODO: refactor too complicated
|
2022-02-21 22:28:30 +02:00
|
|
|
func P2(in string) int {
|
2022-02-19 17:23:06 +02:00
|
|
|
lines := strings.Split(strings.TrimSpace(in), "\n")
|
|
|
|
sum := 0
|
|
|
|
for _, line := range lines {
|
|
|
|
wiringsAndCode := strings.Split(line, " | ")
|
|
|
|
display := findDisplay(wiringsAndCode[0])
|
|
|
|
sum += findCode(wiringsAndCode[1], display)
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum
|
|
|
|
}
|