package main import ( "bufio" "fmt" "os" "strconv" "strings" "time" ) func mustAtoi(line string) int { i, _ := strconv.Atoi(line) return i } func main() { start := time.Now() partOne() duration := time.Since(start) partTwo() duration2 := time.Since(start) fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) } func makeScanner(test bool) *bufio.Scanner { var f *os.File if test { f, _ = os.Open("inputs/testinput") } else { f, _ = os.Open("inputs/input") } reader := bufio.NewReader(f) return bufio.NewScanner(reader) } type monkey struct { items []int operation string // either "plus", "times", or "square" value int // ignored for "square" test int // "divisible by " testpass int // monkey to throw to if test passes testfail int // monkey to throw to if test fails inspections int } func partOne() { scanner := makeScanner(false) currentMonkey := 0 monkeys := []monkey{} // parse monkeys for scanner.Scan() { line := scanner.Text() switch { case strings.HasPrefix(line, "M"): currentMonkey = mustAtoi(strings.Trim(line, "Monkey :")) monkeys = append(monkeys, monkey{items: make([]int, 0)}) case strings.HasPrefix(line, " S"): _, after, _ := strings.Cut(line, ":") items := strings.Split(after, ",") for _, i := range items { monkeys[currentMonkey].items = append(monkeys[currentMonkey].items, mustAtoi(strings.TrimSpace(i))) } case strings.HasPrefix(line, " O"): if strings.Contains(line, "+") { monkeys[currentMonkey].operation = "plus" l := strings.Split(line, " ") monkeys[currentMonkey].value = mustAtoi(l[len(l)-1]) } else if strings.Contains(line, "old * old") { monkeys[currentMonkey].operation = "square" } else if strings.Contains(line, "*") { monkeys[currentMonkey].operation = "times" l := strings.Split(line, " ") monkeys[currentMonkey].value = mustAtoi(l[len(l)-1]) } case strings.HasPrefix(line, " T"): l := strings.Split(line, " ") monkeys[currentMonkey].test = mustAtoi(l[len(l)-1]) case strings.HasPrefix(line, " If t"): l := strings.Split(line, " ") monkeys[currentMonkey].testpass = mustAtoi(l[len(l)-1]) case strings.HasPrefix(line, " If f"): l := strings.Split(line, " ") monkeys[currentMonkey].testfail = mustAtoi(l[len(l)-1]) } } for i := 0; i < 20; i++ { for m := range monkeys { monkeys[m].inspections += len(monkeys[m].items) for _, i := range monkeys[m].items { if monkeys[m].operation == "plus" { i = (i + monkeys[m].value) / 3 } if monkeys[m].operation == "times" { i = (i * monkeys[m].value) / 3 } if monkeys[m].operation == "square" { i = (i * i) / 3 } if i%monkeys[m].test == 0 { monkeys[monkeys[m].testpass].items = append(monkeys[monkeys[m].testpass].items, i) } else { monkeys[monkeys[m].testfail].items = append(monkeys[monkeys[m].testfail].items, i) } } monkeys[m].items = []int{} } } one, two := 0, 0 for _, m := range monkeys { if m.inspections > one && m.inspections > two { one, two = two, m.inspections } else if m.inspections > one { one = m.inspections } } fmt.Println(one * two) } func partTwo() { scanner := makeScanner(false) currentMonkey := 0 monkeys := []monkey{} // parse monkeys for scanner.Scan() { line := scanner.Text() switch { case strings.HasPrefix(line, "M"): currentMonkey = mustAtoi(strings.Trim(line, "Monkey :")) monkeys = append(monkeys, monkey{items: make([]int, 0)}) case strings.HasPrefix(line, " S"): _, after, _ := strings.Cut(line, ":") items := strings.Split(after, ",") for _, i := range items { monkeys[currentMonkey].items = append( monkeys[currentMonkey].items, mustAtoi(strings.TrimSpace(i)), ) } case strings.HasPrefix(line, " O"): if strings.Contains(line, "+") { monkeys[currentMonkey].operation = "plus" l := strings.Split(line, " ") monkeys[currentMonkey].value = mustAtoi(l[len(l)-1]) } else if strings.Contains(line, "old * old") { monkeys[currentMonkey].operation = "square" } else if strings.Contains(line, "*") { monkeys[currentMonkey].operation = "times" l := strings.Split(line, " ") monkeys[currentMonkey].value = mustAtoi(l[len(l)-1]) } case strings.HasPrefix(line, " T"): l := strings.Split(line, " ") monkeys[currentMonkey].test = mustAtoi(l[len(l)-1]) case strings.HasPrefix(line, " If t"): l := strings.Split(line, " ") monkeys[currentMonkey].testpass = mustAtoi(l[len(l)-1]) case strings.HasPrefix(line, " If f"): l := strings.Split(line, " ") monkeys[currentMonkey].testfail = mustAtoi(l[len(l)-1]) } } common := 1 for i := range monkeys { common = common * monkeys[i].test } for j := 0; j < 10000; j++ { for m := range monkeys { monkeys[m].inspections += len(monkeys[m].items) for _, i := range monkeys[m].items { if monkeys[m].operation == "plus" { i = i + monkeys[m].value } if monkeys[m].operation == "times" { i = i * monkeys[m].value } if monkeys[m].operation == "square" { i = i * i } if i%monkeys[m].test == 0 { monkeys[monkeys[m].testpass].items = append(monkeys[monkeys[m].testpass].items, i%common) } else { monkeys[monkeys[m].testfail].items = append(monkeys[monkeys[m].testfail].items, i%common) } } monkeys[m].items = []int{} } } one, two := 0, 0 for _, m := range monkeys { if m.inspections > one && m.inspections > two { one, two = two, m.inspections } else if m.inspections > one { one = m.inspections } } fmt.Println(one * two) }