adventofcode/2022/day11/main.go

189 lines
3.6 KiB
Go

package main
import (
"fmt"
"log"
"strings"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
part1(inp)
part2(inp)
}
func part1(inp []string) {
monkeys := BuildMonkeys(inp, 1)
for i := 0; i < 20; i++ {
for _, m := range monkeys.monkeys {
m.Do(monkeys)
}
}
fmt.Println("# Part 1")
fmt.Println("Monkey Business:", monkeys.Business())
}
func part2(inp []string) {
monkeys := BuildMonkeys(inp, 2)
mod := uint64(1)
for _, m := range monkeys.monkeys {
mod = mod * m.Div
}
for i := 0; i < 10000; i++ {
for _, m := range monkeys.monkeys {
for len(m.Items) > 0 {
m.Inspected++
var v uint64
v, m.Items = m.Items[len(m.Items)-1], m.Items[:len(m.Items)-1]
v = m.Op(v) % mod
if v%m.Div == 0 {
monkeys.Find(m.TrueTo).Catch(v)
} else {
monkeys.Find(m.FalseTo).Catch(v)
}
}
}
}
fmt.Println("# Part 2")
fmt.Println("Monkey Business:", monkeys.Business())
}
type AllMonkeys struct {
monkeys []*Monkey
Part uint64
}
func BuildMonkeys(inp []string, part uint64) *AllMonkeys {
var ret []*Monkey
for i := range inp {
if strings.HasPrefix(inp[i], "Monkey") {
ret = append(ret, NewMonkey(inp[i:]))
}
}
return &AllMonkeys{
monkeys: ret,
Part: part,
}
}
func (a *AllMonkeys) Find(id int) *Monkey {
for i := range a.monkeys {
if a.monkeys[i].Id == id {
return a.monkeys[i]
}
}
return nil
}
func (a *AllMonkeys) Business() uint64 {
// Find the 2 most active monkeys, multiply their inspections together
var top1, top2 *Monkey
for _, m := range a.monkeys {
if top1 == nil {
top1 = m
} else if m.Inspected > top1.Inspected {
top1, top2 = m, top1
} else if top2 == nil || m.Inspected > top2.Inspected {
top2 = m
}
}
fmt.Println("Top Two")
fmt.Println(top1)
fmt.Println(top2)
return top1.Inspected * top2.Inspected
}
type Monkey struct {
Id int
Items []uint64
Inspected uint64
Op func(uint64) uint64
Value uint64
TrueTo int
FalseTo int
Div uint64
}
func NewMonkey(inp []string) *Monkey {
monkey := &Monkey{}
fmt.Sscanf(inp[0], "Monkey %d:", &monkey.Id)
pts := strings.Fields(inp[1])
for i := 2; i < len(pts); i++ {
wrk := strings.TrimSuffix(pts[i], ",")
monkey.Items = append(monkey.Items, h.Atoui(wrk))
}
// Parse out this Monkey's Operation Function
pts = strings.Fields(inp[2])
var p1, p2 uint64
p1S := pts[3]
if p1S != "old" {
p1 = h.Atoui(p1S)
}
p2S := pts[5]
if p2S != "old" {
p2 = h.Atoui(p2S)
}
op := pts[4]
// And the Test
monkey.Div = h.Atoui(inp[3][21:])
switch op {
case "*":
monkey.Op = func(v uint64) uint64 {
first, second := v, v
if p1S != "old" {
first = p1
}
if p2S != "old" {
second = p2
}
return first * second
}
case "+":
monkey.Op = func(v uint64) uint64 {
first, second := v, v
if p1S != "old" {
first = p1
}
if p2S != "old" {
second = p2
}
return first + second
}
}
monkey.TrueTo = h.Atoi(inp[4][29:])
monkey.FalseTo = h.Atoi(inp[5][30:])
return monkey
}
func (m *Monkey) Do(all *AllMonkeys) {
for i := range m.Items {
item := m.Items[i]
pre := item
item = m.Op(item)
if item < pre {
log.Fatalf("%s; Was %d; Now: %d\n", m, pre, item)
}
if all.Part == 1 {
item = item / 3
}
if item%m.Div == 0 {
all.Find(m.TrueTo).Catch(item)
} else {
all.Find(m.FalseTo).Catch(item)
}
m.Inspected++
}
m.Items = []uint64{}
}
func (m *Monkey) Catch(item uint64) {
m.Items = append(m.Items, item)
}
func (m Monkey) String() string {
return fmt.Sprintf("Monkey %d; Inspected %d; Items: %v", m.Id, m.Inspected, m.Items)
}