-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday11.py
86 lines (75 loc) · 2.96 KB
/
day11.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from functools import reduce
class Monkey:
def __init__(self, starting_items, operation, test, bored_divisor):
self.items = starting_items
self.inspection_count = 0
self.operation = operation
self.test = test
self.bored_divisor = bored_divisor
def take_turn(self):
thrown = []
for item in self.items:
worried = self.inspect(item)
worried = int(worried / self.bored_divisor)
thrown.append({ 'monkey': self.throw_to(worried), 'item': worried })
self.items = []
return thrown
def inspect(self, item):
vars = { 'old': item }
exec(self.operation, vars)
self.inspection_count += 1
return vars['new']
def throw_to(self, item):
return self.test['true'] if item % self.test['divisor'] == 0 else self.test['false']
class Troupe:
def __init__(self, filename, bored_divisor=3):
monkey_txt = 'Monkey '
starting_items_txt = ' Starting items: '
operation_txt = ' Operation: '
divisible_test_txt = ' Test: divisible by '
true_txt = ' If true: throw to monkey '
false_txt = ' If false: throw to monkey '
self.monkeys = []
current_monkey = {'bored_divisor': bored_divisor}
with open(filename) as file:
self.data = file.read()
for line in self.data.splitlines():
if line.startswith(starting_items_txt):
current_monkey['starting_items'] = list([int(item) for item in line.replace(starting_items_txt, '').split(',')])
elif line.startswith(operation_txt):
current_monkey['operation'] = compile(line.replace(operation_txt, ''), '<string>', 'exec')
elif line.startswith(divisible_test_txt):
current_test = { 'divisor': int(line.replace(divisible_test_txt, '')) }
elif line.startswith(true_txt):
current_test['true'] = int(line.replace(true_txt, ''))
elif line.startswith(false_txt):
current_test['false'] = int(line.replace(false_txt, ''))
current_monkey['test'] = current_test
self.monkeys.append(Monkey(**current_monkey))
current_monkey = {'bored_divisor': bored_divisor}
self.product = 1
for monkey in self.monkeys:
if self.product % monkey.test['divisor'] != 0:
self.product *= monkey.test['divisor']
def perform_round(self):
for monkey in self.monkeys:
throws = monkey.take_turn()
for throw in throws:
throw['item'] %= self.product
self.monkeys[throw['monkey']].items.append(throw['item'])
def perform_rounds(self, count):
for _ in range(0, count):
self.perform_round()
@property
def monkey_business(self):
largest = sorted([monkey.inspection_count for monkey in self.monkeys], reverse=True)[0:2]
return largest[0] * largest[1]
def main():
troupe = Troupe('../inputs/2022/day11.txt')
troupe.perform_rounds(20)
print(f'Part 1: {troupe.monkey_business}')
troupe = Troupe('../inputs/2022/day11.txt', 1)
troupe.perform_rounds(10_000)
print(f'Part 2: {troupe.monkey_business}')
if __name__ == '__main__':
main()