This commit is contained in:
Gregory 2022-02-19 17:23:06 +02:00
parent 57cb210a45
commit b439301a80
3 changed files with 304 additions and 0 deletions

264
d8/d8.go Normal file
View file

@ -0,0 +1,264 @@
package d8
import (
"log"
"sort"
"strconv"
"strings"
)
func D8(in string) int {
lines := strings.Split(strings.TrimSpace(in), "\n")
sum := 0
for _, line := range lines {
for _, digit := range strings.Split(strings.Split(line, "|")[1], " ") {
if len(digit) == 2 || len(digit) == 3 || len(digit) == 4 || len(digit) == 7 {
sum++
}
}
}
return sum
}
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
}
func D8P2(in string) int {
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
}

37
d8/d8_test.go Normal file
View file

@ -0,0 +1,37 @@
package d8
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestD8(t *testing.T) {
input := `be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce`
assert.EqualValues(t, 26, D8(input))
}
func TestD8P2(t *testing.T) {
input := `be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce`
assert.EqualValues(t, 61229, D8P2(input))
}

View file

@ -14,6 +14,7 @@ import (
"github.com/fotonmoton/aoc2021/d5" "github.com/fotonmoton/aoc2021/d5"
"github.com/fotonmoton/aoc2021/d6" "github.com/fotonmoton/aoc2021/d6"
"github.com/fotonmoton/aoc2021/d7" "github.com/fotonmoton/aoc2021/d7"
"github.com/fotonmoton/aoc2021/d8"
) )
func main() { func main() {
@ -40,4 +41,6 @@ func main() {
fmt.Printf("day 6 part 2: %v\n", d6.D6P2(client.Day(6), 256)) fmt.Printf("day 6 part 2: %v\n", d6.D6P2(client.Day(6), 256))
fmt.Printf("day 7: %v\n", d7.D7(client.Day(7))) fmt.Printf("day 7: %v\n", d7.D7(client.Day(7)))
fmt.Printf("day 7 part 2: %v\n", d7.D7P2(client.Day(7))) fmt.Printf("day 7 part 2: %v\n", d7.D7P2(client.Day(7)))
fmt.Printf("day 8: %v\n", d8.D8(client.Day(8)))
fmt.Printf("day 8 part 2: %v\n", d8.D8P2(client.Day(8)))
} }