diff --git a/2022/d11/ex1/ex1.py b/2022/d11/ex1/ex1.py deleted file mode 100755 index 85f2344..0000000 --- a/2022/d11/ex1/ex1.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python - -import dataclasses -import sys -from collections import Counter, deque -from typing import Literal, Optional - - -@dataclasses.dataclass -class Operation: - lhs: Optional[int] - operator: Literal["+", "*"] - rhs: Optional[int] - - def __call__(self, old: int) -> int: - lhs = old if self.lhs is None else self.lhs - rhs = old if self.rhs is None else self.rhs - - if self.operator == "*": - return lhs * rhs - if self.operator == "+": - return lhs + rhs - assert False - - @classmethod - def from_input(cls, input: str) -> "Operation": - assert input.startswith(" Operation: new = ") - lhs, op, rhs = input.split()[-3:] - - assert op in ("+", "*") # Sanity check - - return cls( - None if lhs == "old" else int(lhs), - op, # type: ignore - None if rhs == "old" else int(rhs), - ) - - -@dataclasses.dataclass -class Monkey: - items: deque[int] - operation: Operation - test_divisor: int - transfer: dict[bool, int] - - @classmethod - def from_input(cls, input: list[str]) -> "Monkey": - # Sanity checks - assert input[0].startswith("Monkey ") - assert "divisible by" in input[3] - assert "true" in input[4] - assert "false" in input[5] - - items = deque( - int(n) for n in input[1].removeprefix(" Starting items: ").split(",") - ) - operation = Operation.from_input(input[2]) - divisor = int(input[3].split()[-1]) - transfer = { - True: int(input[4].split()[-1]), - False: int(input[5].split()[-1]), - } - return Monkey(items, operation, divisor, transfer) - - -def solve(input: list[str]) -> int: - def do_round(monkeys: list[Monkey], counts: dict[int, int]) -> None: - for i, monkey in enumerate(monkeys): - counts[i] += len(monkey.items) - while monkey.items: - item = monkey.items.popleft() - item = monkey.operation(item) - item //= 3 - target = monkey.transfer[(item % monkey.test_divisor) == 0] - monkeys[target].items.append(item) - - monkeys = [Monkey.from_input(monkey_spec.splitlines()) for monkey_spec in input] - counts: Counter[int] = Counter() - - for _ in range(20): - do_round(monkeys, counts) - - ((_, a), (_, b)) = counts.most_common(2) - return a * b - - -def main() -> None: - input = sys.stdin.read().split("\n\n") - print(solve(input)) - - -if __name__ == "__main__": - main() diff --git a/2022/d11/ex1/input b/2022/d11/ex1/input deleted file mode 100644 index 0fa9bdd..0000000 --- a/2022/d11/ex1/input +++ /dev/null @@ -1,55 +0,0 @@ -Monkey 0: - Starting items: 50, 70, 54, 83, 52, 78 - Operation: new = old * 3 - Test: divisible by 11 - If true: throw to monkey 2 - If false: throw to monkey 7 - -Monkey 1: - Starting items: 71, 52, 58, 60, 71 - Operation: new = old * old - Test: divisible by 7 - If true: throw to monkey 0 - If false: throw to monkey 2 - -Monkey 2: - Starting items: 66, 56, 56, 94, 60, 86, 73 - Operation: new = old + 1 - Test: divisible by 3 - If true: throw to monkey 7 - If false: throw to monkey 5 - -Monkey 3: - Starting items: 83, 99 - Operation: new = old + 8 - Test: divisible by 5 - If true: throw to monkey 6 - If false: throw to monkey 4 - -Monkey 4: - Starting items: 98, 98, 79 - Operation: new = old + 3 - Test: divisible by 17 - If true: throw to monkey 1 - If false: throw to monkey 0 - -Monkey 5: - Starting items: 76 - Operation: new = old + 4 - Test: divisible by 13 - If true: throw to monkey 6 - If false: throw to monkey 3 - -Monkey 6: - Starting items: 52, 51, 84, 54 - Operation: new = old * 17 - Test: divisible by 19 - If true: throw to monkey 4 - If false: throw to monkey 1 - -Monkey 7: - Starting items: 82, 86, 91, 79, 94, 92, 59, 94 - Operation: new = old + 7 - Test: divisible by 2 - If true: throw to monkey 5 - If false: throw to monkey 3 diff --git a/2022/d11/ex2/ex2.py b/2022/d11/ex2/ex2.py deleted file mode 100755 index dd947f1..0000000 --- a/2022/d11/ex2/ex2.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python - -import dataclasses -import functools -import sys -from collections import Counter, deque -from typing import Literal, Optional - - -@dataclasses.dataclass -class Operation: - lhs: Optional[int] - operator: Literal["+", "*"] - rhs: Optional[int] - - def __call__(self, old: int) -> int: - lhs = old if self.lhs is None else self.lhs - rhs = old if self.rhs is None else self.rhs - - if self.operator == "*": - return lhs * rhs - if self.operator == "+": - return lhs + rhs - assert False - - @classmethod - def from_input(cls, input: str) -> "Operation": - assert input.startswith(" Operation: new = ") - lhs, op, rhs = input.split()[-3:] - - assert op in ("+", "*") # Sanity check - - return cls( - None if lhs == "old" else int(lhs), - op, # type: ignore - None if rhs == "old" else int(rhs), - ) - - -@dataclasses.dataclass -class Monkey: - items: deque[int] - operation: Operation - test_divisor: int - transfer: dict[bool, int] - - @classmethod - def from_input(cls, input: list[str]) -> "Monkey": - # Sanity checks - assert input[0].startswith("Monkey ") - assert "divisible by" in input[3] - assert "true" in input[4] - assert "false" in input[5] - - items = deque( - int(n) for n in input[1].removeprefix(" Starting items: ").split(",") - ) - operation = Operation.from_input(input[2]) - divisor = int(input[3].split()[-1]) - transfer = { - True: int(input[4].split()[-1]), - False: int(input[5].split()[-1]), - } - return Monkey(items, operation, divisor, transfer) - - -def solve(input: list[str]) -> int: - def do_round(monkeys: list[Monkey], counts: dict[int, int]) -> None: - modulo = functools.reduce( - lambda lhs, rhs: lhs * rhs, - (monkey.test_divisor for monkey in monkeys), - ) - for i, monkey in enumerate(monkeys): - counts[i] += len(monkey.items) - while monkey.items: - item = monkey.items.popleft() - item = monkey.operation(item) - item %= modulo # Keep a reasonable range on this value - target = monkey.transfer[(item % monkey.test_divisor) == 0] - monkeys[target].items.append(item) - - monkeys = [Monkey.from_input(monkey_spec.splitlines()) for monkey_spec in input] - counts: Counter[int] = Counter() - - for _ in range(10_000): - do_round(monkeys, counts) - - ((_, a), (_, b)) = counts.most_common(2) - return a * b - - -def main() -> None: - input = sys.stdin.read().split("\n\n") - print(solve(input)) - - -if __name__ == "__main__": - main() diff --git a/2022/d11/ex2/input b/2022/d11/ex2/input deleted file mode 100644 index 0fa9bdd..0000000 --- a/2022/d11/ex2/input +++ /dev/null @@ -1,55 +0,0 @@ -Monkey 0: - Starting items: 50, 70, 54, 83, 52, 78 - Operation: new = old * 3 - Test: divisible by 11 - If true: throw to monkey 2 - If false: throw to monkey 7 - -Monkey 1: - Starting items: 71, 52, 58, 60, 71 - Operation: new = old * old - Test: divisible by 7 - If true: throw to monkey 0 - If false: throw to monkey 2 - -Monkey 2: - Starting items: 66, 56, 56, 94, 60, 86, 73 - Operation: new = old + 1 - Test: divisible by 3 - If true: throw to monkey 7 - If false: throw to monkey 5 - -Monkey 3: - Starting items: 83, 99 - Operation: new = old + 8 - Test: divisible by 5 - If true: throw to monkey 6 - If false: throw to monkey 4 - -Monkey 4: - Starting items: 98, 98, 79 - Operation: new = old + 3 - Test: divisible by 17 - If true: throw to monkey 1 - If false: throw to monkey 0 - -Monkey 5: - Starting items: 76 - Operation: new = old + 4 - Test: divisible by 13 - If true: throw to monkey 6 - If false: throw to monkey 3 - -Monkey 6: - Starting items: 52, 51, 84, 54 - Operation: new = old * 17 - Test: divisible by 19 - If true: throw to monkey 4 - If false: throw to monkey 1 - -Monkey 7: - Starting items: 82, 86, 91, 79, 94, 92, 59, 94 - Operation: new = old + 7 - Test: divisible by 2 - If true: throw to monkey 5 - If false: throw to monkey 3