🌅
This commit is contained in:
226
solutions/day11/day11.go
Normal file
226
solutions/day11/day11.go
Normal 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((*¤tMonkey).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
|
||||
}
|
||||
(*¤tMonkey).operation = Times
|
||||
(*¤tMonkey).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
|
||||
}
|
||||
(*¤tMonkey).operation = Plus
|
||||
(*¤tMonkey).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
|
||||
}
|
||||
(*¤tMonkey).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
|
||||
}
|
||||
(*¤tMonkey).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
|
||||
}
|
||||
(*¤tMonkey).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()
|
||||
}
|
||||
Reference in New Issue
Block a user