Advertisement
nohar

AoC 2021 Day 14 in Go

Dec 14th, 2021
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 2.59 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "aoc/utils"
  5.     "fmt"
  6.     "math"
  7. )
  8.  
  9. func main() {
  10.     template, rules := parseInput(utils.ReadLines())
  11.     fmt.Println("part 1: ", GrowPolymer(template, rules, 10))
  12.     fmt.Println("part 2: ", GrowPolymer(template, rules, 40))
  13. }
  14.  
  15. type Symbol uint8 // Single-letter symbol (range [0-25])
  16. type Key uint16   // Two-letter key (range [0-675])
  17.  
  18. type Rule struct {
  19.     Symbol Symbol // New byte generated by this rule
  20.     Keys   []Key  // New "rule keys" generated by this rule
  21. }
  22. type RuleSet map[Key]Rule
  23.  
  24. const (
  25.     MaxKey    = 26*26 - 1
  26.     MaxSymbol = 25
  27. )
  28.  
  29. func GrowPolymer(template string, rules RuleSet, gens int) int {
  30.     symCounts := make([]int, MaxSymbol+1)
  31.     keyCounts := make([]int, MaxKey+1)
  32.     initCounters(symCounts, keyCounts, template)
  33.  
  34.     keyCountsNext := make([]int, MaxKey+1)
  35.     swap := func() { keyCounts, keyCountsNext = keyCountsNext, keyCounts }
  36.  
  37.     var count int
  38.     for i := 0; i < gens; i++ {
  39.         for k, rule := range rules {
  40.             count, keyCounts[k] = keyCounts[k], 0
  41.             symCounts[rule.Symbol] += count
  42.             for _, newKey := range rule.Keys {
  43.                 keyCountsNext[newKey] += count
  44.             }
  45.         }
  46.         swap()
  47.     }
  48.     return computeResult(symCounts)
  49. }
  50.  
  51. func initCounters(symCounts, keyCounts []int, template string) {
  52.     for i := 0; i < len(template)-1; i++ {
  53.         k := key(template[i:])
  54.         s := symbol(template[i])
  55.         keyCounts[k]++
  56.         symCounts[s]++
  57.     }
  58.     s := symbol(template[len(template)-1])
  59.     symCounts[s]++
  60. }
  61.  
  62. func computeResult(symCounts []int) int {
  63.     min, max := math.MaxInt, 0
  64.     for _, count := range symCounts {
  65.         if count == 0 {
  66.             continue
  67.         }
  68.         if count > max {
  69.             max = count
  70.         }
  71.         if count < min {
  72.             min = count
  73.         }
  74.     }
  75.     return max - min
  76. }
  77.  
  78. func parseInput(input []string) (string, RuleSet) {
  79.     return input[0], parseRules(input[2:])
  80. }
  81.  
  82. func parseRules(specs []string) RuleSet {
  83.     rules := make(RuleSet, len(specs))
  84.     for _, spec := range specs {
  85.         var keyStr string
  86.         var b byte
  87.         _, err := fmt.Sscanf(spec, "%s -> %c", &keyStr, &b)
  88.         if err != nil {
  89.             panic(err)
  90.         }
  91.         k := key(keyStr)
  92.         rules[k] = Rule{Symbol: symbol(b)}
  93.     }
  94.     for k, rule := range rules {
  95.         key1, key2 := getNewKeys(k, rule.Symbol)
  96.         if _, ok := rules[key1]; ok {
  97.             rule.Keys = append(rule.Keys, key1)
  98.         }
  99.         if _, ok := rules[key2]; ok {
  100.             rule.Keys = append(rule.Keys, key2)
  101.         }
  102.         rules[k] = rule
  103.     }
  104.     return rules
  105. }
  106.  
  107. func key(str string) Key {
  108.     return Key(symbol(str[0]))*26 + Key(symbol(str[1]))
  109. }
  110.  
  111. func symbol(b byte) Symbol {
  112.     return Symbol(b - 'A')
  113. }
  114.  
  115. func getNewKeys(k Key, s Symbol) (Key, Key) {
  116.     left, right := k/26, k%26
  117.     return left*26 + Key(s), Key(s)*26 + right
  118. }
  119.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement