|
|
@@ -0,0 +1,140 @@
|
|
|
+import os, argparse
|
|
|
+from typing import List
|
|
|
+
|
|
|
+DEBUG = False
|
|
|
+#DEBUG = True
|
|
|
+
|
|
|
+def debug_print(s):
|
|
|
+ if DEBUG:
|
|
|
+ print(f"DEBUG: {s}")
|
|
|
+
|
|
|
+
|
|
|
+def solve_task(lines):
|
|
|
+ monkeys = []
|
|
|
+ current_monkey = []
|
|
|
+ for line in lines:
|
|
|
+ if len(line) == 0:
|
|
|
+ monkeys.append(Monkey.from_line(current_monkey))
|
|
|
+ current_monkey = []
|
|
|
+ else:
|
|
|
+ current_monkey.append(line)
|
|
|
+ if(len(current_monkey) != 0):
|
|
|
+ monkeys.append(Monkey.from_line(current_monkey))
|
|
|
+
|
|
|
+ for i, monkey in enumerate(monkeys):
|
|
|
+ print(f"Monkey {i}:")
|
|
|
+ print(f"{monkey}\n")
|
|
|
+
|
|
|
+ game = KeepAwayGame(monkeys)
|
|
|
+ game.do_rounds(10000)
|
|
|
+ for i, monkey in enumerate(monkeys):
|
|
|
+ print(f"Monkey {i} inspected items : {monkey.items_inspected} times.")
|
|
|
+
|
|
|
+ print(f"Monkey business: {game.monkey_business()}")
|
|
|
+
|
|
|
+
|
|
|
+class Monkey:
|
|
|
+ def __init__(self, items, operation, modulo, true_monkey, false_monkey) -> None:
|
|
|
+ self._items = items
|
|
|
+ self._operation = operation
|
|
|
+ self._modulo = modulo
|
|
|
+ self._true_monkey = true_monkey
|
|
|
+ self._false_monkey = false_monkey
|
|
|
+ self.items_inspected = 0
|
|
|
+
|
|
|
+ def __str__(self):
|
|
|
+ to_return = f" Items: {str(self._items)[1:-1]}\n"
|
|
|
+ to_return += f" Operation: {self._operation}\n"
|
|
|
+ to_return += f" Test: divisible by {self._modulo}\n"
|
|
|
+ to_return += f" If true: throw to monkey {self._true_monkey}\n"
|
|
|
+ to_return += f" If false: throw to monkey {self._false_monkey}"
|
|
|
+ return to_return
|
|
|
+
|
|
|
+ def give(self, item):
|
|
|
+ self._items.append(item)
|
|
|
+
|
|
|
+ def take_round(self, throw_function):
|
|
|
+ while len(self._items):
|
|
|
+ item = self._items.pop(0)
|
|
|
+ #debug_print(f" Monkey inspects an item with a worry level of {item}.")
|
|
|
+ self.items_inspected += 1
|
|
|
+ item = self._operation(item)
|
|
|
+ debug_print(f" New worry level: {item}.")
|
|
|
+ #item = item // 3
|
|
|
+ #debug_print(f" Monkey gets bored with item. Worry level is divided by 3 to {item}.")
|
|
|
+ if (item % self._modulo) == 0:
|
|
|
+ debug_print(f" Test: true")
|
|
|
+ throw_function(self._true_monkey, item)
|
|
|
+ #debug_print(f" Item with worry level {item} is thrown to monkey {self._true_monkey}.")
|
|
|
+ else:
|
|
|
+ #debug_print(f" Test: false")
|
|
|
+ throw_function(self._false_monkey, item)
|
|
|
+ #debug_print(f" Item with worry level {item} is thrown to monkey {self._false_monkey}.")
|
|
|
+
|
|
|
+ def from_line(lines) -> None:
|
|
|
+ starting_items = [int(i) for i in lines[1].split(':')[1].split(',')]
|
|
|
+ operation = Monkey.create_operation_from_line(lines[2])
|
|
|
+ modulo = int(lines[3].split("by")[1])
|
|
|
+ iftrue = int(lines[4].split("monkey")[1])
|
|
|
+ iffalse = int(lines[5].split("monkey")[1])
|
|
|
+ return Monkey(starting_items, operation, modulo, iftrue, iffalse)
|
|
|
+
|
|
|
+ def create_operation_from_line(line):
|
|
|
+ operation = line.split(':')[1].strip()
|
|
|
+ global_dir = {}
|
|
|
+ exec(f"""def func(old):
|
|
|
+ {operation}
|
|
|
+ return new""", global_dir)
|
|
|
+ return global_dir["func"]
|
|
|
+
|
|
|
+
|
|
|
+class KeepAwayGame:
|
|
|
+ def __init__(self, monkeys: List[Monkey]) -> None:
|
|
|
+ self.monkeys = monkeys
|
|
|
+ self.global_modulo = 1
|
|
|
+ for monkey in monkeys:
|
|
|
+ self.global_modulo *= monkey._modulo
|
|
|
+ print(f"Game initialized with global modulo: {self.global_modulo}")
|
|
|
+
|
|
|
+
|
|
|
+ def do_rounds(self, n = 1):
|
|
|
+ for round in range(n):
|
|
|
+ debug_print(f"Round {round}")
|
|
|
+ for i, monkey in enumerate(self.monkeys):
|
|
|
+ debug_print(f"Monkey {i}:")
|
|
|
+ monkey.take_round(self.throw)
|
|
|
+
|
|
|
+ def monkey_business(self):
|
|
|
+ inspections = [m.items_inspected for m in self.monkeys]
|
|
|
+ inspections.sort()
|
|
|
+ return inspections[-1] * inspections[-2]
|
|
|
+
|
|
|
+ def throw(self, recipient, worry_level):
|
|
|
+ worry_level = worry_level % self.global_modulo
|
|
|
+ self.monkeys[recipient].give(worry_level)
|
|
|
+
|
|
|
+
|
|
|
+def read_lines(filename):
|
|
|
+ lines = []
|
|
|
+ with open(filename) as infile:
|
|
|
+ for raw_line in infile:
|
|
|
+ line = raw_line.rstrip()
|
|
|
+ lines.append(line)
|
|
|
+ return lines
|
|
|
+
|
|
|
+
|
|
|
+def parse_arguments():
|
|
|
+ parser = argparse.ArgumentParser(description="Script that solves the case",epilog="Have a nice day!")
|
|
|
+ parser.add_argument('filename', nargs='?', default="example.txt", help='Input file')
|
|
|
+ args = parser.parse_args()
|
|
|
+ return args
|
|
|
+
|
|
|
+
|
|
|
+def main():
|
|
|
+ args = parse_arguments()
|
|
|
+ lines = read_lines(args.filename)
|
|
|
+ solve_task(lines)
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|