130 lines
3.0 KiB
Go
130 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"math"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/thoas/go-funk"
|
|
)
|
|
|
|
func main() {
|
|
inputBytes, _ := os.ReadFile("input.txt")
|
|
input := strings.Split(string(inputBytes), "\n")
|
|
|
|
log.Println("Puzzle 1:", puzzle1(input))
|
|
log.Println("Puzzle 2:", puzzle2(input))
|
|
}
|
|
|
|
const (
|
|
len1 = 2
|
|
len4 = 4
|
|
len7 = 3
|
|
len8 = 7
|
|
)
|
|
|
|
func puzzle1(input []string) int {
|
|
inputRegex := regexp.MustCompile(`([a-g]+)`)
|
|
count := 0
|
|
for _, line := range input {
|
|
matches := inputRegex.FindAllString(line, 14)
|
|
if len(matches) != 14 {
|
|
panic("Invalid input")
|
|
}
|
|
outputValues := matches[10:]
|
|
for _, outputValue := range outputValues {
|
|
if l := len(outputValue); l == len1 || l == len4 || l == len7 || l == len8 {
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func puzzle2(input []string) int {
|
|
inputRegex := regexp.MustCompile(`([a-g]+)`)
|
|
count := 0
|
|
for _, line := range input {
|
|
matches := inputRegex.FindAllString(line, 14)
|
|
if len(matches) != 14 {
|
|
panic("Invalid input")
|
|
}
|
|
lineDigits := matches[:10]
|
|
digits := [10]string{}
|
|
// Map by length
|
|
lenGroups := make(map[int][]string)
|
|
for _, digit := range lineDigits {
|
|
l := len(digit)
|
|
lenGroups[l] = append(lenGroups[l], digit)
|
|
}
|
|
// Get known digits
|
|
digits[1] = lenGroups[len1][0]
|
|
digits[4] = lenGroups[len4][0]
|
|
digits[7] = lenGroups[len7][0]
|
|
digits[8] = lenGroups[len8][0]
|
|
// Deducing the rest
|
|
// 9 (Length 6): Four chars are the same with 4
|
|
for i, digit := range lenGroups[6] {
|
|
if countIntersectChars(digits[4], digit) == 4 {
|
|
digits[9] = digit
|
|
lenGroups[6] = append(lenGroups[6][:i], lenGroups[6][i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
// 0 (Length 6): Three chars are the same with 7
|
|
for i, digit := range lenGroups[6] {
|
|
if countIntersectChars(digits[7], digit) == 3 {
|
|
digits[0] = digit
|
|
lenGroups[6] = append(lenGroups[6][:i], lenGroups[6][i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
// 6 (Length 6): Last remaining from lenGroup[6]
|
|
digits[6] = lenGroups[6][0]
|
|
// 3 (Length 5): Two chars are the same with 1
|
|
for i, digit := range lenGroups[5] {
|
|
if countIntersectChars(digits[1], digit) == 2 {
|
|
digits[3] = digit
|
|
lenGroups[5] = append(lenGroups[5][:i], lenGroups[5][i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
// 2 (Length 5): Two chars are the same with 4
|
|
for i, digit := range lenGroups[5] {
|
|
if countIntersectChars(digits[4], digit) == 2 {
|
|
digits[2] = digit
|
|
lenGroups[5] = append(lenGroups[5][:i], lenGroups[5][i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
// 5 (Length 5): Last remaining from lenGroup[5]
|
|
digits[5] = lenGroups[5][0]
|
|
// Add output values to count
|
|
outputValues := matches[10:]
|
|
for i, outputValue := range funk.ReverseStrings(outputValues) {
|
|
l := len(outputValue)
|
|
for j, digit := range digits {
|
|
if l != len(digit) {
|
|
continue
|
|
}
|
|
if countIntersectChars(outputValue, digit) == l {
|
|
count += j * int(math.Pow(10, float64(i)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func countIntersectChars(a, b string) int {
|
|
count := 0
|
|
for _, c := range []byte(a) {
|
|
if funk.Contains([]byte(b), c) {
|
|
count++
|
|
}
|
|
}
|
|
return count
|
|
}
|