This commit is contained in:
2022-12-23 19:45:56 -08:00
commit 8792e5275a
77 changed files with 31154 additions and 0 deletions

226
solutions/day11/day11.go Normal file
View File

@@ -0,0 +1,226 @@
package day11
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type Operation int
const (
Times Operation = iota
Plus
Square
)
type Monkey struct {
items []int
operation Operation
operation_by int
divisible_by int
if_true int
if_false int
}
func printMonkeys(monkeys []*Monkey) {
for monkey_no, monkey := range monkeys {
if monkey != nil {
fmt.Printf("Monkey #%d: ", monkey_no)
var items []int = (*monkey).items
for idx, item := range items {
fmt.Printf("%d", item)
if idx != len(items)-1 {
fmt.Printf(", ")
}
}
fmt.Println()
}
}
}
func lcm(items []int) int {
worstCase := 1
smallest := items[0]
for _, val := range items {
worstCase *= val
if val < smallest {
smallest = val
}
}
retval := worstCase
for candidate := worstCase; candidate > 2; candidate -= smallest {
works := true
for _, val := range items {
works = works && (candidate%val == 0)
}
if works {
retval = candidate
}
}
return retval
}
func runRound(monkeys *[]*Monkey, counts *[]int, ceiling int) {
//three := big.NewInt(3)
for monkey_no, monkey := range *monkeys {
if monkey == nil {
break
}
//fmt.Printf("Monkey %d:\n", monkey_no)
items := (*monkey).items
(*monkey).items = []int{}
for _, item := range items {
(*counts)[monkey_no] += 1
//fmt.Printf(" Monkey inspects an item with a worry level of %d.\n", item)
var result int = item
switch monkey.operation {
case Times:
result = item * monkey.operation_by
//fmt.Printf(" Worry level is multiplied by %d to %d.\n", monkey.operation_by, result)
case Square:
result = item * item
//fmt.Printf(" Worry level is squared to %d.\n", result)
case Plus:
result = item + monkey.operation_by
//fmt.Printf(" Worry level is increased by %d to %d.\n", monkey.operation_by, result)
default:
//fmt.Printf("PANIC: Don't understand operation\n", monkey.operation_by)
return
}
result %= ceiling
//result = result.Div(result, three)
//fmt.Printf(" Monkey gets bored with item. Worry level is divided by 3 to %d.\n", result)
var targetMonkey int
if result%monkey.divisible_by == 0 {
//fmt.Printf(" Current worry level is divisible by %d.\n", monkey.divisible_by)
targetMonkey = monkey.if_true
} else {
//fmt.Printf(" Current worry level is not divisible by %d.\n", monkey.divisible_by)
targetMonkey = monkey.if_false
}
//fmt.Printf(" Item with worry level %d is thrown to monkey %d.\n", result, targetMonkey)
(*monkeys)[targetMonkey].items = append((*monkeys)[targetMonkey].items, result)
}
}
}
func Run(filename string) {
file, err := os.Open(filename)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
monkeys := []*Monkey{nil, nil, nil, nil, nil, nil, nil, nil}
inspectionCounts := []int{0, 0, 0, 0, 0, 0, 0, 0}
divisors := []int{}
var currentMonkey *Monkey = nil
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "Monkey ") {
number, err := strconv.Atoi(line[7 : len(line)-1])
if err != nil {
fmt.Println("Error parsing monkey number", line[7:len(line)-1])
return
}
newMonkey := Monkey{[]int{}, Times, 0, 0, 0, 0}
monkeys[number] = &newMonkey
currentMonkey = &newMonkey
} else if strings.HasPrefix(line, " Starting items: ") {
list := line[18:]
splits := strings.Split(list, ", ")
if currentMonkey == nil {
fmt.Println("Item list with no monkey")
return
}
for _, split := range splits {
splitInt, err := strconv.Atoi(split)
if err != nil {
fmt.Println("Error parsing monkey's item", split)
return
}
(*currentMonkey).items = append((*&currentMonkey).items, splitInt)
}
} else if strings.HasPrefix(line, " Operation: new = old * ") {
amtString := line[25:]
if amtString == "old" {
(*currentMonkey).operation = Square
} else {
amt, err := strconv.Atoi(amtString)
if err != nil {
fmt.Println("Error parsing operation number", amtString)
return
}
(*&currentMonkey).operation = Times
(*&currentMonkey).operation_by = amt
}
} else if strings.HasPrefix(line, " Operation: new = old + ") {
amtString := line[25:]
amt, err := strconv.Atoi(amtString)
if err != nil {
fmt.Println("Error parsing plus operation number", amtString)
return
}
(*&currentMonkey).operation = Plus
(*&currentMonkey).operation_by = amt
} else if strings.HasPrefix(line, " Test: divisible by ") {
amtString := line[21:]
amt, err := strconv.Atoi(amtString)
if err != nil {
fmt.Println("Error parsing divisible by number", amtString)
return
}
(*&currentMonkey).divisible_by = amt
divisors = append(divisors, amt)
} else if strings.HasPrefix(line, " If true: throw to monkey ") {
amtString := line[29:]
amt, err := strconv.Atoi(amtString)
if err != nil {
fmt.Println("Error parsing if true number", amtString)
return
}
(*&currentMonkey).if_true = amt
} else if strings.HasPrefix(line, " If false: throw to monkey ") {
amtString := line[30:]
amt, err := strconv.Atoi(amtString)
if err != nil {
fmt.Println("Error parsing if false number", amtString)
return
}
(*&currentMonkey).if_false = amt
} else if len(line) == 0 {
} else {
fmt.Printf("Invalid line: '%s'\n", line)
return
}
}
ceiling := lcm(divisors)
printMonkeys(monkeys)
for i := 0; i < 10000; i++ {
if i%100 == 0 {
fmt.Println("Running round", i)
}
runRound(&monkeys, &inspectionCounts, ceiling)
//printMonkeys(monkeys)
}
for monkey_no, count := range inspectionCounts {
fmt.Printf("Monkey %d inspected items %d times\n", monkey_no, count)
}
file.Close()
}