aoc21/d14/p1.go
2022-05-11 00:09:37 +03:00

68 lines
1.6 KiB
Go

package d14
import (
"strings"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)
func reduce[S any, A any](slice []S, f func(elm S, acc A) A, acc A) A {
for _, elm := range slice {
acc = f(elm, acc)
}
return acc
}
func makePairs(template string) map[string]int {
pairs := make(map[string]int)
for i := 0; i < len(template)-1; i++ {
pairs[string(template[i])+string(template[i+1])] = 1
}
return pairs
}
func templateAndInstructions(in string) (string, map[string]string) {
parts := strings.Split(strings.TrimSpace(in), "\n\n")
instructions := make(map[string]string)
for _, pair := range strings.Split(parts[1], "\n") {
mapping := strings.Split(pair, " -> ")
instructions[mapping[0]] = mapping[1]
}
return parts[0], instructions
}
func count(template string, instructions map[string]string, runs int) map[string]int {
init := func(char string, acc map[string]int) map[string]int { acc[char]++; return acc }
counts := reduce(strings.Split(template, ""), init, make(map[string]int))
pairs := makePairs(template)
for i := 0; i < runs; i++ {
for pair, count := range maps.Clone(pairs) {
left := pair[:1]
right := pair[1:]
middle := instructions[pair]
pairs[pair] -= count
pairs[left+middle] += count
pairs[middle+right] += count
counts[middle] += count
}
}
return counts
}
func countPolymer(in string, runs int) int {
template, instructions := templateAndInstructions(in)
counts := maps.Values(count(template, instructions, runs))
slices.Sort(counts)
max := counts[len(counts)-1]
min := counts[0]
return max - min
}
func P1(in string) int {
return countPolymer(in, 10)
}