2021 Day 14 Part 2
This commit is contained in:
parent
39c4916c51
commit
6ccd3ed4b0
1 changed files with 29 additions and 92 deletions
|
|
@ -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]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue