213 lines
5.0 KiB
Go
213 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
aoc "AoC/2021/common"
|
|
"bufio"
|
|
"strings"
|
|
)
|
|
|
|
func inSlice(a string, slice []string) bool {
|
|
for _, b := range slice {
|
|
if a == b {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Returns elements that are present in a or b
|
|
func union(a []string, b []string) []string {
|
|
for _, c := range b {
|
|
if !inSlice(c, a) {
|
|
a = append(a, c)
|
|
}
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
// Return all elements that are present in a, but not in b
|
|
func complement(a []string, b []string) []string {
|
|
var temp []string
|
|
for _, c := range a {
|
|
if !inSlice(c, b) {
|
|
temp = append(temp, c)
|
|
}
|
|
}
|
|
|
|
return temp
|
|
}
|
|
|
|
func match(a []string, b []string) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
|
|
for _, s := range a {
|
|
if !inSlice(s, b) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func main() {
|
|
aoc := aoc.New(2021, 8)
|
|
|
|
aoc.Test(`acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf`, []int{0, 5353})
|
|
|
|
aoc.Test(`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
|
|
`, []int{26, 61229})
|
|
|
|
aoc.Solution(1, func(input *bufio.Scanner) int {
|
|
count := 0
|
|
for input.Scan() {
|
|
line := input.Text()
|
|
lineOutput := strings.TrimSpace(strings.Split(line, "|")[1])
|
|
outputs := strings.Split(lineOutput, " ")
|
|
|
|
for _, output := range outputs {
|
|
// Detect unique digits 1, 4 ,7 and 8
|
|
if len(output) == 2 || len(output) == 3 || len(output) == 4 || len(output) == 7 {
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
|
|
return count
|
|
})
|
|
|
|
aoc.Solution(2, func(input *bufio.Scanner) int {
|
|
sum := 0
|
|
for input.Scan() {
|
|
line := input.Text()
|
|
parts := strings.Split(line, "|")
|
|
|
|
lineDigits := strings.TrimSpace(parts[0])
|
|
digits := strings.Split(lineDigits, " ")
|
|
|
|
mapping := make(map[int] []string)
|
|
count := make(map[string] int)
|
|
|
|
for _, digit := range digits {
|
|
// Determine part of the mappnig using unique characters
|
|
if len(digit) == 2 {
|
|
mapping[1] = strings.Split(digit, "")
|
|
} else if len(digit) == 3 {
|
|
mapping[7] = strings.Split(digit, "")
|
|
} else if len(digit) == 4 {
|
|
mapping[4] = strings.Split(digit, "")
|
|
} else if len(digit) == 7 {
|
|
mapping[8] = strings.Split(digit, "")
|
|
}
|
|
|
|
// Count how often each segment appears
|
|
for _, c := range digit {
|
|
count[string(c)]++
|
|
}
|
|
}
|
|
|
|
// Figure out what some of the elements map to
|
|
{
|
|
// b is the only segments that appears 6 times
|
|
var b string
|
|
for k, v := range count {
|
|
if v == 6 {
|
|
b = k
|
|
break
|
|
}
|
|
}
|
|
|
|
// e is the only segments that appears 4 times
|
|
var e string
|
|
for k, v := range count {
|
|
if v == 4 {
|
|
e = k
|
|
break
|
|
}
|
|
}
|
|
|
|
// f is the only segment that appears 9 times
|
|
var f string
|
|
for k, v := range count {
|
|
if v == 9 {
|
|
f = k
|
|
break
|
|
}
|
|
}
|
|
|
|
// Both a and c appear 8 times, however using the known characters we can find a
|
|
a := complement(union(mapping[4], mapping[7]), mapping[4])[0]
|
|
|
|
// Both a and c appear 8 times, however since we know a we can find c
|
|
var c string
|
|
for k, v := range count {
|
|
if v == 8 && k != a {
|
|
c = k
|
|
break
|
|
}
|
|
}
|
|
|
|
// Both d and g apear 7 times, however using known characrers and the fact that we know e we can still find g
|
|
eg := complement(mapping[8], union(mapping[4], mapping[7]))
|
|
var g string
|
|
for _, c := range eg {
|
|
if c != e {
|
|
g = c
|
|
break
|
|
}
|
|
}
|
|
|
|
// Both d and g apear 7 times, however using known characrers and the fact that we know e we can still find d
|
|
bd := complement(mapping[4], mapping[1])
|
|
var d string
|
|
for _, c := range bd {
|
|
if c != b {
|
|
d = c
|
|
break
|
|
}
|
|
}
|
|
|
|
// All segments are now known so we can fill in the rest of the map
|
|
mapping[0] = []string{a, b, c, e, f, g}
|
|
mapping[2] = []string{a, c, d, e, g}
|
|
mapping[3] = []string{a, c, d, f, g}
|
|
mapping[5] = []string{a, b, d, f, g}
|
|
mapping[6] = []string{a, b, d, e, f, g}
|
|
mapping[9] = []string{a, b, c, d, f, g}
|
|
}
|
|
|
|
lineOutput := strings.TrimSpace(parts[1])
|
|
outputs := strings.Split(lineOutput, " ")
|
|
|
|
// Using the completed mapping determine what the display is showing
|
|
display := 0
|
|
for _, output := range outputs {
|
|
for k, v := range mapping {
|
|
if !match(strings.Split(output, ""), v) {
|
|
continue
|
|
}
|
|
|
|
display *= 10
|
|
display += k
|
|
}
|
|
}
|
|
|
|
sum += display
|
|
}
|
|
|
|
return sum
|
|
})
|
|
}
|