Monkey in the middle
Monkeys throwing stuff around and making you worried
package problems
import (
"fmt"
"sort"
"strings"
"github.com/xxxx/advent/internal"
)
type day11 struct {
lines []string
}
type monkey struct {
items []int
operation func(int) int
test func(int) bool
true_monkey int
false_monkey int
total_inspect int
}
func Day11(part int, file string) int {
in := day11{
lines: internal.Read(file),
}
switch part {
case 1:
return in.part_one()
case 2:
return in.part_two()
default:
return 0
}
}
func build_operation(a int, operand string) func(old int) int {
// anonymous function for monkey to use
// a is a constant
switch operand {
case "+":
return func(old int) int {
return old + a
}
case "*":
return func(old int) int {
return old * a
}
case "^":
return func(old int) int {
return old * old
}
default:
panic(fmt.Sprintf("unknown operand: %s", operand))
}
}
func build_test(a int) func(old int) bool {
// anonymous function for monkey to use
// a is a constant
return func(old int) bool {
return old%a == 0
}
}
func read_input_into_monkeys(lines []string) map[int]*monkey {
monkeys := make(map[int]*monkey)
for i, line := range lines {
monkey_number := i / 7
m, found := monkeys[monkey_number]
if found {
switch i % 7 {
case 1: // starting items
data := strings.Split(line, ":")[1]
m.items = internal.StrSliceToIntSlice(strings.Split(strings.TrimSpace(data), ","))
case 2: // operation
data := strings.Split(line, "=")[1]
if strings.Contains(data, "+") {
a := internal.StrToInt(strings.TrimSpace(strings.Split(data, "+")[1]))
m.operation = build_operation(a, "+")
} else if strings.Contains(data, "*") {
constant := strings.TrimSpace(strings.Split(data, "*")[1])
if constant == "old" {
m.operation = build_operation(0, "^")
} else {
a := internal.StrToInt(strings.TrimSpace(strings.Split(data, "*")[1]))
m.operation = build_operation(a, "*")
}
} else {
panic(data)
}
case 3: // test
a := internal.StrToInt(strings.TrimSpace(strings.Split(line, "by")[1]))
m.test = build_test(a)
case 4: // true monkey
a := internal.StrToInt(strings.TrimSpace(strings.Split(line, "monkey")[1]))
m.true_monkey = a
case 5: // false monkey
a := internal.StrToInt(strings.TrimSpace(strings.Split(line, "monkey")[1]))
m.false_monkey = a
case 6:
default:
panic(line)
}
} else {
monkeys[monkey_number] = &monkey{
items: nil,
operation: nil,
test: nil,
true_monkey: 0,
total_inspect: 0,
}
}
}
return monkeys
}
func (input day11) part_one() int {
monkeys := read_input_into_monkeys(input.lines)
for round := 0; round < 20; round++ {
for i := 0; i < len(monkeys); i++ {
monkey := monkeys[i]
for _, item := range monkey.items {
worry_level := monkey.operation(item) / 3
if monkey.test(worry_level) {
monkeys[monkey.true_monkey].items = append(monkeys[monkey.true_monkey].items, worry_level)
} else {
monkeys[monkey.false_monkey].items = append(monkeys[monkey.false_monkey].items, worry_level)
}
}
monkey.total_inspect = monkey.total_inspect + len(monkey.items)
monkey.items = []int{}
}
}
monkey_inspect_count := []int{}
for i := 0; i < len(monkeys); i++ {
monkey_inspect_count = append(monkey_inspect_count, monkeys[i].total_inspect)
}
sort.Sort(sort.Reverse(sort.IntSlice(monkey_inspect_count)))
return monkey_inspect_count[0] * monkey_inspect_count[1]
}
func (input day11) part_two() int {
monkeys := read_input_into_monkeys(input.lines)
for round := 0; round < 10000; round++ {
fmt.Println(round)
for i := 0; i < len(monkeys); i++ {
monkey := monkeys[i]
for _, item := range monkey.items {
worry_level := monkey.operation(item)
if worry_level > 9699690 {
worry_level = worry_level % 9699690
}
if monkey.test(worry_level) {
monkeys[monkey.true_monkey].items = append(monkeys[monkey.true_monkey].items, worry_level)
} else {
monkeys[monkey.false_monkey].items = append(monkeys[monkey.false_monkey].items, worry_level)
}
}
monkey.total_inspect = monkey.total_inspect + len(monkey.items)
monkey.items = []int{}
}
}
monkey_inspect_count := []int{}
for i := 0; i < len(monkeys); i++ {
monkey_inspect_count = append(monkey_inspect_count, monkeys[i].total_inspect)
}
sort.Sort(sort.Reverse(sort.IntSlice(monkey_inspect_count)))
return monkey_inspect_count[0] * monkey_inspect_count[1]
}