So, now that you’re foraging through the jungle alone, you have discovered that Monkeys have stolen your items and are tossing them around. Use MATH to build a shotgun out of bamboo reeds and vines and stop the Monkeys!

No wait, that’s not friendly. Instead maybe calculate the rounds your items spend being tossed around based on some Mysterious Monkey Criteria and try to get your items back. There is probably some easy library to process the input, but that’s not how I’m rolling on these puzzles, so like 90% of this problem was processing the “Almost a dictionary input” into a format that json.loads would accept and transform into a dictionary. Then massaging that data just a bit more because my loop was adding an empty item each iteration and breaking things, but I can’t just lop that item off because the initial data doesn’t have an empty item. That’s easily fixed by adding an empty item to the initial data.

Part 1 does this loop for 20 rounds.

Part 2 does it for 10,000 rounds. (with slight modification to the code)

This is where some fancy library would probably be better, but instead I just, left my laptop running and made lunch…. and played some Fortnite… and probably made supper too, I’m not sure I am not there yet, it’s still lunch time while I am writing this. I am feeling confident it will work though. It hasn’t creashed yet at least. But maybe It will run out of memory before it can finish…. Or the heat death of the universe….

Or I can use the “Modulo Trick” which is to reduce the numbers down each round by a common multiple. Which literally finished in seconds, and was correct the first try.

Also, I can’t spell “Monkeys” but fuck it, I am leaving it.

import math
import json

with open("Day11Input.txt") as file:
    data = file.read()

split = data.split("\n\n")

monkies = {}

for each in split:
    each = each.replace('Monkey ', '{"')
    each = each.replace(': ', '": "')
    each = each.replace('\n  ', '", "')
    each = each.replace(':", "Starting ', '": {"')
    each = each.replace('new = old ', '')
    each = each.replace('divisible by ', '')
    each = each.replace('  If t', 'T')
    each = each.replace('  If f', 'F')
    each = each.replace('throw to monkey ', '')
    each = each + '"}}'
    monkies.update(json.loads(each))

monkey_list = monkies.keys()
num_monks = len(monkey_list)

# Part1
# rounds = 20
# Part2
rounds = 10000

common_multiple = 1
# print(monkies['3'])
for monk in range(0, num_monks):
    monkies[str(monk)]["item_count"] = 0
    monkies[str(monk)]["items"] = ", "+monkies[str(monk)]["items"]
    common_multiple *= int(monkies[str(monk)]["Test"])

for i in range(rounds):
    for monk in range(0, num_monks):
        # print(monk)
        items = monkies[str(monk)]["items"].split(", ")
        # print(items)
        if len(items) > 0:
            for item in items[1:]:
                monkies[str(monk)]["item_count"] += 1
                operations = monkies[str(monk)]["Operation"].split(" ")
                if operations[1] == "old":
                    # Part 1
                    # test_case = math.floor((int(item) * int(int(item)))/3)
                    # Part 2
                    test_case = math.floor((int(item) * int(int(item))))
                elif operations[0] == "*":
                    # Part 1
                    # test_case = math.floor((int(item) * int(operations[1]))/3)
                    # Part 2
                    test_case = math.floor((int(item) * int(operations[1])))
                else:
                    # Part 1
                    # test_case = math.floor((int(item) + int(operations[1]))/3)
                    # Part 2
                    test_case = math.floor((int(item) + int(operations[1])))
                if test_case % int(monkies[str(monk)]["Test"]) == 0:
                    throw_to = monkies[str(monk)]["True"]
                else:
                    throw_to = monkies[str(monk)]["False"]
                monkies[throw_to]["items"] = monkies[throw_to]["items"] + ", "+str(test_case%common_multiple)
        monkies[str(monk)]["items"] = ""

# print(monkies)

item_counts = []
for monk in range(0, num_monks):
    item_counts.append(monkies[str(monk)]["item_count"])

item_counts.sort(reverse=True)
print(item_counts[0]*item_counts[1])
# 25738411485