github.com/frodejac/aoc-2022@v0.0.0-20221213081734-037c741b1c89/internal/aoc/day10/day10.go (about) 1 package day10 2 3 import ( 4 "sort" 5 "strconv" 6 "strings" 7 8 "github.com/frodejac/aoc-2022/pkg/datastructures/stack" 9 ) 10 11 type monkey struct { 12 inventory *stack.Stack[int] 13 operation func(int) int 14 mod int 15 dstTrue int 16 dstFalse int 17 opsCounter *int 18 } 19 20 func parseInventory(inventoryRaw string) *stack.Stack[int] { 21 inventory := stack.New([]int{}) 22 itemsRaw := strings.Split(inventoryRaw, ": ")[1] 23 items := strings.Split(itemsRaw, ", ") 24 for _, item := range items { 25 worryLevel, _ := strconv.Atoi(item) 26 inventory.Push(worryLevel) 27 } 28 return inventory 29 } 30 31 func parseOperation(operationRaw string) func(int) int { 32 operationRaw = strings.Split(operationRaw, "new = ")[1] 33 parts := strings.Split(operationRaw, " ") 34 35 operation := func(old int) int { 36 var op2 int 37 switch parts[2] { 38 case "old": 39 op2 = old 40 default: 41 op2, _ = strconv.Atoi(parts[2]) 42 } 43 switch parts[1] { 44 case "+": 45 return old + op2 46 case "*": 47 return old * op2 48 default: 49 panic("Unknown operation") 50 } 51 } 52 return operation 53 } 54 55 func parseMod(modRaw string) int { 56 modRaw = strings.TrimSpace(modRaw) 57 parts := strings.Split(modRaw, " ") 58 mod, _ := strconv.Atoi(parts[3]) 59 return mod 60 } 61 62 func parseDestination(destinationRaw string) int { 63 destinationRaw = strings.TrimSpace(destinationRaw) 64 parts := strings.Split(destinationRaw, " ") 65 dst, _ := strconv.Atoi(parts[5]) 66 return dst 67 } 68 69 func parseMonkey(monkeyRaw string) monkey { 70 monkey := monkey{} 71 lines := strings.Split(monkeyRaw, "\n") 72 monkey.inventory = parseInventory(lines[1]) 73 monkey.operation = parseOperation(lines[2]) 74 monkey.mod = parseMod(lines[3]) 75 monkey.dstTrue = parseDestination(lines[4]) 76 monkey.dstFalse = parseDestination(lines[5]) 77 monkey.opsCounter = new(int) 78 return monkey 79 } 80 81 func parseInput(input string) []monkey { 82 monkeysRaw := strings.Split(input, "\n\n") 83 monkeys := []monkey{} 84 for _, monkeyRaw := range monkeysRaw { 85 monkeys = append(monkeys, parseMonkey(monkeyRaw)) 86 } 87 return monkeys 88 } 89 90 type Day10 struct { 91 input []byte 92 } 93 94 func Solver(input []byte) *Day10 { 95 return &Day10{input: input} 96 } 97 98 func (d *Day10) SolvePart1() string { 99 monkeys := parseInput(string(d.input)) 100 101 for i := 0; i < 20; i++ { 102 for _, monkey := range monkeys { 103 itemCount := monkey.inventory.Size() 104 for i := 0; i < itemCount; i++ { 105 *monkey.opsCounter++ 106 item := monkey.inventory.Pop() 107 newItem := monkey.operation(item) 108 newItem = newItem / 3 109 if (newItem % monkey.mod) == 0 { 110 monkeys[monkey.dstTrue].inventory.Push(newItem) 111 } else { 112 monkeys[monkey.dstFalse].inventory.Push(newItem) 113 } 114 } 115 } 116 } 117 opsCounters := []int{} 118 for _, monkey := range monkeys { 119 opsCounters = append(opsCounters, *monkey.opsCounter) 120 } 121 sort.Slice(opsCounters[:], func(i, j int) bool { 122 return opsCounters[i] > opsCounters[j] 123 }) 124 monkeyBusiness := opsCounters[0] * opsCounters[1] 125 return strconv.Itoa(monkeyBusiness) 126 } 127 128 func (d *Day10) SolvePart2() string { 129 monkeys := parseInput(string(d.input)) 130 131 commonDivisor := 1 132 for _, monkey := range monkeys { 133 commonDivisor *= monkey.mod 134 } 135 136 for i := 0; i < 10000; i++ { 137 for _, monkey := range monkeys { 138 itemCount := monkey.inventory.Size() 139 for i := 0; i < itemCount; i++ { 140 *monkey.opsCounter++ 141 item := monkey.inventory.Pop() 142 newItem := monkey.operation(item) 143 newItem = newItem % commonDivisor 144 if (newItem % monkey.mod) == 0 { 145 monkeys[monkey.dstTrue].inventory.Push(newItem) 146 } else { 147 monkeys[monkey.dstFalse].inventory.Push(newItem) 148 } 149 } 150 } 151 } 152 opsCounters := []int{} 153 for _, monkey := range monkeys { 154 opsCounters = append(opsCounters, *monkey.opsCounter) 155 } 156 sort.Slice(opsCounters[:], func(i, j int) bool { 157 return opsCounters[i] > opsCounters[j] 158 }) 159 monkeyBusiness := opsCounters[0] * opsCounters[1] 160 return strconv.Itoa(monkeyBusiness) 161 }