From 4804e6b4ab1874713cea4147e99a59c73a0dbc1f Mon Sep 17 00:00:00 2001 From: Jeremy Kaplan Date: Mon, 13 Dec 2021 21:59:30 -0800 Subject: [PATCH] 2021 Day 14 Part 1 --- 2021/day14/main.go | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 2021/day14/main.go diff --git a/2021/day14/main.go b/2021/day14/main.go new file mode 100644 index 0000000..d5ea60e --- /dev/null +++ b/2021/day14/main.go @@ -0,0 +1,128 @@ +package main + +import ( + "errors" + "fmt" + "io" + "sort" + "strings" + + "github.com/jdkaplan/advent-of-code/aoc" +) + +func main() { + text := aoc.Input().ReadFile("day14.txt") + start, rules := parse(text) + fmt.Println(run(start, rules, 10)) +} + +type Rule struct { + a, b, i rune +} + +func parse(text string) (string, []Rule) { + start, lines := aoc.Cut(text, "\n\n") + var rules []Rule + for _, l := range strings.Split(lines, "\n") { + pair, ins := aoc.Cut(l, " -> ") + a, b := (pair[0]), pair[1] + rules = append(rules, Rule{rune(a), rune(b), rune(ins[0])}) + } + return start, rules +} + +type Re map[rune]map[rune]rune + +func (r Re) Get(a, b rune) (rune, bool) { + inner, ok := r[a] + if !ok { + return rune(0), false + } + ins, ok := inner[b] + return ins, ok +} + +func (r Re) Put(a, b, i rune) { + inner, ok := r[a] + if !ok { + inner = make(map[rune]rune) + r[a] = inner + } + inner[b] = i +} + +func run(s string, rules []Rule, steps int) int { + re := make(Re) + for _, r := range rules { + re.Put(r.a, r.b, r.i) + } + + for i := 0; i < steps; i++ { + s = expand(s, 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 expand(s string, re Re) string { + w := pairs(s) + var sb strings.Builder + for { + a, b, err := w.Next() + 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() +} + +type Window struct { + prev rune + r *strings.Reader +} + +func (w *Window) Next() (a rune, b rune, err error) { + a = w.prev + b, _, err = w.r.ReadRune() + w.prev = b + return +} + +func pairs(s string) *Window { + w := &Window{r: strings.NewReader(s)} + _, _, err := w.Next() + if err != nil { + panic(err) + } + 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]++ + } +}