|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +import re |
| 4 | + |
| 5 | +monkeys = {} |
| 6 | + |
| 7 | +class IsHuman(RuntimeError): |
| 8 | + pass |
| 9 | + |
| 10 | +class Monkey: |
| 11 | + setting = False |
| 12 | + |
| 13 | + def __init__(self, name, operation): |
| 14 | + number_format = re.compile("^(?P<num>[0-9]+)$") |
| 15 | + calc_format = re.compile("^(?P<m1>[a-z]+) (?P<op>[-+*/]) (?P<m2>[a-z]+)$") |
| 16 | + |
| 17 | + self.operation = operation |
| 18 | + self.name = name |
| 19 | + self.val = None |
| 20 | + if (m := number_format.match(self.operation)): |
| 21 | + self.val = int(m["num"]) |
| 22 | + else: |
| 23 | + m = calc_format.match(self.operation) |
| 24 | + self.m1 = m["m1"] |
| 25 | + self.op = m["op"] |
| 26 | + if self.name == "root": |
| 27 | + self.op = "==" |
| 28 | + self.m2 = m["m2"] |
| 29 | + |
| 30 | + def value(self): |
| 31 | + if self.setting and self.name == "humn": |
| 32 | + raise IsHuman |
| 33 | + |
| 34 | + if self.val is not None: |
| 35 | + return self.val |
| 36 | + |
| 37 | + if self.op == "+": |
| 38 | + self.val = monkeys[self.m1].value() + monkeys[self.m2].value() |
| 39 | + elif self.op == "-": |
| 40 | + self.val = monkeys[self.m1].value() - monkeys[self.m2].value() |
| 41 | + elif self.op == "*": |
| 42 | + self.val = monkeys[self.m1].value() * monkeys[self.m2].value() |
| 43 | + elif self.op == "/": |
| 44 | + self.val = monkeys[self.m1].value() // monkeys[self.m2].value() |
| 45 | + |
| 46 | + return self.val |
| 47 | + |
| 48 | + def set_equal(self, value): |
| 49 | + if self.name == "humn": |
| 50 | + self.val = value |
| 51 | + return |
| 52 | + |
| 53 | + try: |
| 54 | + left = monkeys[self.m1].value() |
| 55 | + except IsHuman: |
| 56 | + left = None |
| 57 | + |
| 58 | + try: |
| 59 | + right = monkeys[self.m2].value() |
| 60 | + except IsHuman: |
| 61 | + right = None |
| 62 | + |
| 63 | + if self.op == "==": |
| 64 | + if right is not None: |
| 65 | + monkeys[self.m1].set_equal(right) |
| 66 | + if left is not None: |
| 67 | + monkeys[self.m2].set_equal(left) |
| 68 | + elif self.op == "+": |
| 69 | + if right is not None: |
| 70 | + monkeys[self.m1].set_equal(value - right) |
| 71 | + if left is not None: |
| 72 | + monkeys[self.m2].set_equal(value - left) |
| 73 | + elif self.op == "-": |
| 74 | + if right is not None: |
| 75 | + monkeys[self.m1].set_equal(value + right) |
| 76 | + if left is not None: |
| 77 | + monkeys[self.m2].set_equal(left - value) |
| 78 | + elif self.op == "*": |
| 79 | + if right is not None: |
| 80 | + monkeys[self.m1].set_equal(value // right) |
| 81 | + if left is not None: |
| 82 | + monkeys[self.m2].set_equal(value // left) |
| 83 | + elif self.op == "/": |
| 84 | + if right is not None: |
| 85 | + monkeys[self.m1].set_equal(value * right) |
| 86 | + if left is not None: |
| 87 | + monkeys[self.m2].set_equal(left // value) |
| 88 | + |
| 89 | + def __str__(self): |
| 90 | + return f"<{self.__class__.__name__}: {self.name} = {self.operation} ({self.val})>" |
| 91 | + |
| 92 | + |
| 93 | +monkey_format = re.compile("^(?P<name>[a-z]+): (?P<op>.*)$") |
| 94 | + |
| 95 | +lines = [row.strip() for row in open("21.input").readlines()] |
| 96 | + |
| 97 | +for line in lines: |
| 98 | + m = monkey_format.match(line) |
| 99 | + monkeys[m["name"]] = Monkey(m["name"], m["op"]) |
| 100 | + |
| 101 | +Monkey.setting = True |
| 102 | +monkeys["root"].set_equal(None) |
| 103 | +Monkey.setting = False |
| 104 | + |
| 105 | +print(monkeys["humn"].value()) |
0 commit comments