Day 11
This commit is contained in:
305
day11/common/monkey.go
Normal file
305
day11/common/monkey.go
Normal file
@@ -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
|
||||
}
|
||||
28
day11/ex1/main.go
Normal file
28
day11/ex1/main.go
Normal file
@@ -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])
|
||||
}
|
||||
28
day11/ex2/main.go
Normal file
28
day11/ex2/main.go
Normal file
@@ -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])
|
||||
}
|
||||
Reference in New Issue
Block a user