advent-of-code-2021/8/solve.go

106 lines
2.2 KiB
Go
Raw Permalink Normal View History

2021-12-08 12:10:41 +00:00
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
sum1 := 0
sum2 := 0
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
parts := strings.Split(s.Text(), " | ")
samples := strings.Split(parts[0], " ")
output := strings.Split(parts[1], " ")
// sort alphabetically
for i := range samples {
samples[i] = sortStr(samples[i])
}
for i := range output {
output[i] = sortStr(output[i])
}
// sort by length
sort.Slice(samples, func(i, j int) bool { return len(samples[i]) < len(samples[j]) })
// save known ones
numbers := map[string]int{}
numbers[samples[0]] = 1
numbers[samples[1]] = 7
numbers[samples[2]] = 4
numbers[samples[9]] = 8
fourWithoutOne := substr(samples[2], samples[0])
var xi string
// iterate over 5 segment digits
for _, digit := range samples[3:6] {
// only 3 has both right segments of 1
if hasSegments(digit, samples[0]) {
numbers[digit] = 3
xi = substr(digit, samples[0])
// only 5 has the middle and top-left segments of 4
} else if hasSegments(digit, fourWithoutOne) {
numbers[digit] = 5
} else {
numbers[digit] = 2
}
}
// iterate over 6 segment digits
for _, digit := range samples[6:9] {
// only 0 doesn't have all middle segments
if !hasSegments(digit, xi) {
numbers[digit] = 0
// between 6 and 9, only 9 has both right segments of 1
} else if hasSegments(digit, samples[0]) {
numbers[digit] = 9
} else {
numbers[digit] = 6
}
}
for _, digit := range output {
if len(digit) == 2 || len(digit) == 3 || len(digit) == 4 || len(digit) == 7 {
sum1++
}
}
sum2 += 1000 * numbers[output[0]] + 100 * numbers[output[1]] + 10 * numbers[output[2]] + numbers[output[3]]
}
fmt.Println(sum1)
fmt.Println(sum2)
}
func hasSegments(s string, segments string) bool {
res := true
for _, segment := range segments {
if !strings.ContainsRune(s, segment) {
res = false
}
}
return res
}
// subtract string
func substr(a, b string) string {
for _, char := range b {
a = strings.ReplaceAll(a, string(char), "")
}
return a
}
func sortStr(s string) string {
r := []rune(s)
sort.Slice(r, func(i, j int) bool { return r[i] < r[j] })
return string(r)
}