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

2021 Day 14 Part 2

This commit is contained in:
Jeremy Kaplan 2021-12-14 09:37:01 -08:00
commit 6ccd3ed4b0

View file

@ -14,7 +14,7 @@ func main() {
text := aoc.Input().ReadFile("day14.txt") text := aoc.Input().ReadFile("day14.txt")
start, rules := parse(text) start, rules := parse(text)
fmt.Println(run(start, rules, 10)) fmt.Println(run(start, rules, 10))
fmt.Println(run2(start, rules, 40)) fmt.Println(run(start, rules, 40))
} }
type Rule struct { type Rule struct {
@ -32,24 +32,22 @@ func parse(text string) (string, []Rule) {
return start, rules return start, rules
} }
type Re map[rune]map[rune]rune type Pair [2]rune
func (r Re) Get(a, b rune) (rune, bool) { type Re map[Pair]rune
inner, ok := r[a]
func (r Re) Sub(p Pair) []Pair {
ins, ok := r[p]
if !ok { if !ok {
return rune(0), false return []Pair{p}
} }
ins, ok := inner[b] p1 := Pair{p[0], ins}
return ins, ok p2 := Pair{ins, p[1]}
return []Pair{p1, p2}
} }
func (r Re) Put(a, b, i rune) { func (r Re) Put(a, b, i rune) {
inner, ok := r[a] r[Pair{a, b}] = i
if !ok {
inner = make(map[rune]rune)
r[a] = inner
}
inner[b] = i
} }
func run(s string, rules []Rule, steps int) int { func run(s string, rules []Rule, steps int) int {
@ -58,58 +56,20 @@ func run(s string, rules []Rule, steps int) int {
re.Put(r.a, r.b, r.i) re.Put(r.a, r.b, r.i)
} }
pc := make(map[Pair]int)
for _, p := range allPairs(s) {
pc[p]++
}
first := rune(s[0])
for i := 0; i < steps; i++ { for i := 0; i < steps; i++ {
s = expand(s, re) pc = expand(pc, re)
}
counts := countChars(s)
var chars []rune
for r := range counts {
chars = append(chars, r)
}
sort.Slice(chars, func(i, j int) bool {
return counts[chars[i]] < counts[chars[j]]
})
min, max := chars[0], chars[len(chars)-1]
return counts[max] - counts[min]
}
func run2(s string, rules []Rule, steps int) int {
re := make(Re)
for _, r := range rules {
re.Put(r.a, r.b, r.i)
} }
counts := make(map[rune]int) counts := make(map[rune]int)
counts[rune(s[0])]++ counts[first]++
for p, c := range pc {
type node struct { counts[p[1]] += c
s string
steps int
}
var queue []node
for _, s := range allPairs(s) {
queue = append(queue, node{s: s, steps: steps})
}
for len(queue) > 0 {
fmt.Println(len(queue))
n := queue[0]
queue = queue[1:]
s, steps := n.s, n.steps
for ; steps > 0 && len(s) < 1<<15; steps-- {
s = expand(s, re)
}
if steps == 0 {
counts[rune(s[0])]--
for r, n := range countChars(s) {
counts[r] += n
}
} else {
for _, s := range allPairs(s) {
queue = append(queue, node{s: s, steps: steps})
}
}
} }
var chars []rune var chars []rune
@ -123,8 +83,8 @@ func run2(s string, rules []Rule, steps int) int {
return counts[max] - counts[min] return counts[max] - counts[min]
} }
func allPairs(s string) []string { func allPairs(s string) []Pair {
var out []string var out []Pair
w := pairs(s) w := pairs(s)
for { for {
a, b, err := w.Next() a, b, err := w.Next()
@ -133,27 +93,18 @@ func allPairs(s string) []string {
} else if err != nil { } else if err != nil {
panic(err) panic(err)
} }
out = append(out, string([]rune{a, b})) out = append(out, Pair{a, b})
} }
} }
func expand(s string, re Re) string { func expand(pc map[Pair]int, re Re) map[Pair]int {
w := pairs(s) out := make(map[Pair]int)
var sb strings.Builder for p, c := range pc {
for { for _, b := range re.Sub(p) {
a, b, err := w.Next() out[b] += c
if errors.Is(err, io.EOF) {
sb.WriteRune(a)
break
} else if err != nil {
panic(err)
}
sb.WriteRune(a)
if i, ok := re.Get(a, b); ok {
sb.WriteRune(i)
} }
} }
return sb.String() return out
} }
type Window struct { type Window struct {
@ -176,17 +127,3 @@ func pairs(s string) *Window {
} }
return w return w
} }
func countChars(s string) map[rune]int {
r := strings.NewReader(s)
m := make(map[rune]int)
for {
c, _, err := r.ReadRune()
if errors.Is(err, io.EOF) {
return m
} else if err != nil {
panic(err)
}
m[c]++
}
}