From c98367aca09395355bcedadf8a043ce48e86587a Mon Sep 17 00:00:00 2001 From: Pierre Jeanjean Date: Sun, 11 Dec 2022 14:57:54 +0100 Subject: [PATCH] Day 11 --- day11/common/monkey.go | 305 +++++++++++++++++++++++++++++++++++++++++ day11/ex1/main.go | 28 ++++ day11/ex2/main.go | 28 ++++ 3 files changed, 361 insertions(+) create mode 100644 day11/common/monkey.go create mode 100644 day11/ex1/main.go create mode 100644 day11/ex2/main.go diff --git a/day11/common/monkey.go b/day11/common/monkey.go new file mode 100644 index 0000000..60a46d3 --- /dev/null +++ b/day11/common/monkey.go @@ -0,0 +1,305 @@ +package common + +import ( + "bufio" + "strconv" + "strings" +) + + +type WorryLevel interface { + Plus(int) WorryLevel + Times(int) WorryLevel + Power(int) WorryLevel + Relief() WorryLevel + Modulo(int) int +} + + +type WorryLevelWithRelief struct { + level int +} + +func (worryLevel WorryLevelWithRelief) Plus(operand int) WorryLevel { + return WorryLevelWithRelief{worryLevel.level + operand} +} + +func (worryLevel WorryLevelWithRelief) Times(operand int) WorryLevel { + return WorryLevelWithRelief{worryLevel.level * operand} +} + +func (worryLevel WorryLevelWithRelief) Power(operand int) WorryLevel { + result := 1 + for i := 0; i < operand; i++ { + result *= worryLevel.level + } + return WorryLevelWithRelief{result} +} + +func (worryLevel WorryLevelWithRelief) Relief() WorryLevel { + return WorryLevelWithRelief{worryLevel.level / 3} +} + +func (worryLevel WorryLevelWithRelief) Modulo(operand int) int { + return worryLevel.level % operand +} + + +type WorryLevelWithoutReliefBase struct { + level int +} + +func (worryLevel *WorryLevelWithoutReliefBase) Plus(operand int) WorryLevel { + return &WorryLevelWithoutReliefPlus{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefBase) Times(operand int) WorryLevel { + return &WorryLevelWithoutReliefTimes{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefBase) Power(operand int) WorryLevel { + return &WorryLevelWithoutReliefPower{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefBase) Relief() WorryLevel { + return worryLevel +} + +func (worryLevel *WorryLevelWithoutReliefBase) Modulo(operand int) int { + return worryLevel.level % operand +} + + +type WorryLevelWithoutReliefPlus struct { + worryLevel WorryLevel + operand int + modulos map[int]int +} + +func (worryLevel *WorryLevelWithoutReliefPlus) Plus(operand int) WorryLevel { + return &WorryLevelWithoutReliefPlus{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefPlus) Times(operand int) WorryLevel { + return &WorryLevelWithoutReliefTimes{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefPlus) Power(operand int) WorryLevel { + return &WorryLevelWithoutReliefPower{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefPlus) Relief() WorryLevel { + return worryLevel +} + +func (worryLevel *WorryLevelWithoutReliefPlus) Modulo(operand int) int { + if val, ok := worryLevel.modulos[operand]; ok { + return val + } else { + val = (worryLevel.worryLevel.Modulo(operand) + worryLevel.operand % operand) % operand + worryLevel.modulos[operand] = val + return val + } +} + + +type WorryLevelWithoutReliefTimes struct { + worryLevel WorryLevel + operand int + modulos map[int]int +} + +func (worryLevel *WorryLevelWithoutReliefTimes) Plus(operand int) WorryLevel { + return &WorryLevelWithoutReliefPlus{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefTimes) Times(operand int) WorryLevel { + return &WorryLevelWithoutReliefTimes{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefTimes) Power(operand int) WorryLevel { + return &WorryLevelWithoutReliefPower{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefTimes) Relief() WorryLevel { + return worryLevel +} + +func (worryLevel *WorryLevelWithoutReliefTimes) Modulo(operand int) int { + if val, ok := worryLevel.modulos[operand]; ok { + return val + } else { + val = (worryLevel.worryLevel.Modulo(operand) * (worryLevel.operand % operand)) % operand + worryLevel.modulos[operand] = val + return val + } +} + + +type WorryLevelWithoutReliefPower struct { + worryLevel WorryLevel + operand int + modulos map[int]int +} + +func (worryLevel *WorryLevelWithoutReliefPower) Plus(operand int) WorryLevel { + return &WorryLevelWithoutReliefPlus{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefPower) Times(operand int) WorryLevel { + return &WorryLevelWithoutReliefTimes{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefPower) Power(operand int) WorryLevel { + return &WorryLevelWithoutReliefPower{worryLevel, operand, make(map[int]int)} +} + +func (worryLevel *WorryLevelWithoutReliefPower) Relief() WorryLevel { + return worryLevel +} + +func (worryLevel *WorryLevelWithoutReliefPower) Modulo(operand int) int { + if val, ok := worryLevel.modulos[operand]; ok { + return val + } else { + mod := worryLevel.worryLevel.Modulo(operand) + result := 1 + for i := 0; i < worryLevel.operand; i++ { + result *= mod + } + val = result % operand + worryLevel.modulos[operand] = val + return val + } +} + + +type Item struct { + worryLevel WorryLevel +} + +func NewItem(worryLevel WorryLevel) *Item { + return &Item{worryLevel} +} + + +type Operation interface { + Apply(WorryLevel) WorryLevel +} + + +type Addition struct { + operand int +} + +func (operation Addition) Apply(operand WorryLevel) WorryLevel { + return operand.Plus(operation.operand) +} + + +type Multiplication struct { + operand int +} + +func (operation Multiplication) Apply(operand WorryLevel) WorryLevel { + return operand.Times(operation.operand) +} + + +type Power struct { + operand int +} + +func (operation Power) Apply(operand WorryLevel) WorryLevel { + return operand.Power(operation.operand) +} + + +type Test struct { + divisible int + targets map[bool]*Monkey +} + + +type Monkey struct { + heldItems []Item + operation Operation + test Test + nInspections int +} + +func (monkey *Monkey) ReceiveItem(item Item) { + monkey.heldItems = append(monkey.heldItems, item) +} + +func (monkey *Monkey) GetNumberOfInspections() int { + return monkey.nInspections +} + +func (monkey *Monkey) NextRound() { + for len(monkey.heldItems) > 0 { + monkey.nInspections++ + item := monkey.heldItems[0] + monkey.heldItems = monkey.heldItems[1:] + worryLevel := item.worryLevel + worryLevel = monkey.operation.Apply(worryLevel) + worryLevel = worryLevel.Relief() + monkey.test.targets[worryLevel.Modulo(monkey.test.divisible) == 0].ReceiveItem(Item{worryLevel}) + } +} + + +func Parse(scanner bufio.Scanner, relief bool) []Monkey { + monkeys := []Monkey{} + targets := make(map[int]map[bool]int) + var monkey Monkey + + for scanner.Scan() { + line := scanner.Text() + + if line == "" { + monkeys = append(monkeys, monkey) + } else if line[:6] == "Monkey" { + monkey = Monkey{} + } else if line[:16] == " Starting items" { + items := strings.Split(line[18:], ", ") + for _, item := range(items) { + itemInt, _ := strconv.Atoi(item) + if (relief) { + monkey.heldItems = append(monkey.heldItems, *NewItem(WorryLevelWithRelief{itemInt})) + } else { + monkey.heldItems = append(monkey.heldItems, *NewItem(&WorryLevelWithoutReliefBase{itemInt})) + } + } + } else if line[:11] == " Operation" { + if line[23] == '+' { + operand, _ := strconv.Atoi(line[25:]) + monkey.operation = Addition{operand} + } else if line[23] == '*' { + operand, err := strconv.Atoi(line[25:]) + if err == nil { + monkey.operation = Multiplication{operand} + } else { + monkey.operation = Power{2} + } + } + } else if line[:6] == " Test" { + divisible, _ := strconv.Atoi(line[21:]) + monkey.test.divisible = divisible + targets[len(monkeys)] = make(map[bool]int) + } else if line[:11] == " If true" { + targets[len(monkeys)][true] = int(line[29] - '0') + } else if line[:12] == " If false" { + targets[len(monkeys)][false] = int(line[30] - '0') + } + } + monkeys = append(monkeys, monkey) + + for i, target := range targets { + monkeys[i].test.targets = make(map[bool]*Monkey) + monkeys[i].test.targets[true] = &monkeys[target[true]] + monkeys[i].test.targets[false] = &monkeys[target[false]] + } + + return monkeys +} diff --git a/day11/ex1/main.go b/day11/ex1/main.go new file mode 100644 index 0000000..134956a --- /dev/null +++ b/day11/ex1/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "aoc2022/day11/common" + "bufio" + "fmt" + "os" + "sort" +) + +func main() { + monkeys := common.Parse(*bufio.NewScanner(os.Stdin), true) + + for i := 0; i < 20; i++ { + for j := 0; j < len(monkeys); j++ { + monkey := &monkeys[j] + monkey.NextRound() + } + } + + nInspections := make([]int, len(monkeys)) + for i := 0; i < len(monkeys); i++ { + nInspections[i] = monkeys[i].GetNumberOfInspections() + } + sort.Ints(nInspections) + + fmt.Println(nInspections[len(nInspections)-1] * nInspections[len(nInspections)-2]) +} diff --git a/day11/ex2/main.go b/day11/ex2/main.go new file mode 100644 index 0000000..455ddd3 --- /dev/null +++ b/day11/ex2/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "aoc2022/day11/common" + "bufio" + "fmt" + "os" + "sort" +) + +func main() { + monkeys := common.Parse(*bufio.NewScanner(os.Stdin), false) + + for i := 0; i < 10000; i++ { + for j := 0; j < len(monkeys); j++ { + monkey := &monkeys[j] + monkey.NextRound() + } + } + + nInspections := make([]int, len(monkeys)) + for i := 0; i < len(monkeys); i++ { + nInspections[i] = monkeys[i].GetNumberOfInspections() + } + sort.Ints(nInspections) + + fmt.Println(nInspections[len(nInspections)-1] * nInspections[len(nInspections)-2]) +}