2021 Day 8
This commit is contained in:
parent
0f454c5d1f
commit
2d203e541e
3 changed files with 336 additions and 0 deletions
188
2021/day8/main.go
Normal file
188
2021/day8/main.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jdkaplan/advent-of-code/aoc"
|
||||
"github.com/jdkaplan/advent-of-code/aoc/stringset"
|
||||
)
|
||||
|
||||
func main() {
|
||||
lines := aoc.Input().ReadLines("day8.txt")
|
||||
fmt.Println(part1(lines))
|
||||
fmt.Println(part2(lines))
|
||||
}
|
||||
|
||||
func part1(lines []string) int {
|
||||
var count int
|
||||
for _, l := range lines {
|
||||
_, out := aoc.Cut(l, " | ")
|
||||
for _, p := range strings.Fields(out) {
|
||||
if _, ok := easy(p); ok {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func part2(lines []string) int {
|
||||
var sum int
|
||||
for _, l := range lines {
|
||||
pats, out := aoc.Cut(l, " | ")
|
||||
d := infer(strings.Fields(pats))
|
||||
n, err := d.decode(strings.Fields(out))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sum += n
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func easy(segments string) (int, bool) {
|
||||
switch len(segments) {
|
||||
// 0 segments => {}
|
||||
// 1 segments => {}
|
||||
case 2:
|
||||
return 1, true
|
||||
case 3:
|
||||
return 7, true
|
||||
case 4:
|
||||
return 4, true
|
||||
case 7:
|
||||
return 8, true
|
||||
default:
|
||||
// 5 segments => {2, 3, 5}
|
||||
// 6 segments => {0, 6, 9}
|
||||
return -1, false
|
||||
}
|
||||
}
|
||||
|
||||
// AA
|
||||
// B C
|
||||
// DD
|
||||
// E F
|
||||
// GG
|
||||
type Display struct {
|
||||
A, B, C, D, E, F, G string
|
||||
}
|
||||
|
||||
func (d *Display) String() string {
|
||||
return strings.Join([]string{d.A, d.B, d.C, d.D, d.E, d.F, d.G}, " ")
|
||||
}
|
||||
|
||||
func infer(pats []string) *Display {
|
||||
var one, four, seven, eight stringset.StringSet
|
||||
var fives, sixes []stringset.StringSet
|
||||
for _, pat := range pats {
|
||||
s := stringset.Runes(pat)
|
||||
switch len(s) {
|
||||
case 2:
|
||||
one = s
|
||||
case 3:
|
||||
seven = s
|
||||
case 4:
|
||||
four = s
|
||||
case 5:
|
||||
fives = append(fives, s)
|
||||
case 6:
|
||||
sixes = append(sixes, s)
|
||||
case 7:
|
||||
eight = s
|
||||
default:
|
||||
panic("WTF")
|
||||
}
|
||||
}
|
||||
a := seven.Minus(one)
|
||||
ifives := stringset.Intersect(fives...)
|
||||
g := ifives.Minus(seven.Union(four))
|
||||
d := ifives.Minus(a.Union(g))
|
||||
e := eight.Minus(four.Union(a).Union(g))
|
||||
five := stringset.Intersect(sixes...).Union(d)
|
||||
six := five.Union(e)
|
||||
c := eight.Minus(six)
|
||||
// good
|
||||
two := stringset.Union(a, c, d, e, g)
|
||||
var three stringset.StringSet
|
||||
for _, s := range fives {
|
||||
if s.Equal(five) || s.Equal(two) {
|
||||
continue
|
||||
}
|
||||
three = s
|
||||
}
|
||||
if len(three) == 0 {
|
||||
panic("WAT")
|
||||
}
|
||||
f := three.Minus(two)
|
||||
b := eight.Minus(stringset.Union(a, c, d, e, f, g))
|
||||
|
||||
return &Display{
|
||||
A: a.Only(),
|
||||
B: b.Only(),
|
||||
C: c.Only(),
|
||||
D: d.Only(),
|
||||
E: e.Only(),
|
||||
F: f.Only(),
|
||||
G: g.Only(),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Display) decode(pats []string) (int, error) {
|
||||
var n int
|
||||
for _, p := range pats {
|
||||
n *= 10
|
||||
x, err := d.decodeSingle(p)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
n += x
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (d *Display) decodeSingle(pat string) (int, error) {
|
||||
s := stringset.Runes(pat)
|
||||
t0 := stringset.Slice([]string{d.A, d.B, d.C, d.E, d.F, d.G})
|
||||
t1 := stringset.Slice([]string{d.C, d.F})
|
||||
t2 := stringset.Slice([]string{d.A, d.C, d.D, d.E, d.G})
|
||||
t3 := stringset.Slice([]string{d.A, d.C, d.D, d.F, d.G})
|
||||
t4 := stringset.Slice([]string{d.B, d.C, d.D, d.F})
|
||||
t5 := stringset.Slice([]string{d.A, d.B, d.D, d.F, d.G})
|
||||
t6 := stringset.Slice([]string{d.A, d.B, d.D, d.E, d.F, d.G})
|
||||
t7 := stringset.Slice([]string{d.A, d.C, d.F})
|
||||
t8 := stringset.Slice([]string{d.A, d.B, d.C, d.D, d.E, d.F, d.G})
|
||||
t9 := stringset.Slice([]string{d.A, d.B, d.C, d.D, d.F, d.G})
|
||||
if s.Equal(t0) {
|
||||
return 0, nil
|
||||
}
|
||||
if s.Equal(t1) {
|
||||
return 1, nil
|
||||
}
|
||||
if s.Equal(t2) {
|
||||
return 2, nil
|
||||
}
|
||||
if s.Equal(t3) {
|
||||
return 3, nil
|
||||
}
|
||||
if s.Equal(t4) {
|
||||
return 4, nil
|
||||
}
|
||||
if s.Equal(t5) {
|
||||
return 5, nil
|
||||
}
|
||||
if s.Equal(t6) {
|
||||
return 6, nil
|
||||
}
|
||||
if s.Equal(t7) {
|
||||
return 7, nil
|
||||
}
|
||||
if s.Equal(t8) {
|
||||
return 8, nil
|
||||
}
|
||||
if s.Equal(t9) {
|
||||
return 9, nil
|
||||
}
|
||||
return -1, fmt.Errorf("decode segments: %s", s)
|
||||
}
|
||||
Loading…
Reference in a new issue