Watch
1
0
Fork
You've already forked advent-of-code
0

2021 Day 8

This commit is contained in:
Jeremy Kaplan 2021-12-07 23:42:54 -08:00
commit 2d203e541e
3 changed files with 336 additions and 0 deletions

188
2021/day8/main.go Normal file
View 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)
}