| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- 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()
|