Advertisement
Guest User

AoC 2022 Day 11

a guest
Jan 2nd, 2023
1,001
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.21 KB | None | 0 0
  1. # aoc202211.py
  2.  
  3. import pathlib
  4. import re
  5. import sys
  6.  
  7. from math import prod
  8. from typing import TypeAlias
  9.  
  10. # Typing aliases
  11. Monkeys: TypeAlias = list[dict[str, list]]
  12.  
  13.  
  14. def parse(puzzle_input: str) -> Monkeys:
  15.     """Parse input"""
  16.     monkeys: Monkeys = []
  17.     lines: list[str] = puzzle_input.splitlines()
  18.     for line in lines:
  19.         match = re.search(r"Monkey (\d+):", line)
  20.         if match:
  21.             monkey = {"number": match.group(1)}
  22.             monkeys.append(monkey)
  23.         match = re.search(r"Starting items: (.*)", line)
  24.         if match:
  25.             items = [int(item) for item in match.group(1).split(",")]
  26.             monkey["starting_items"] = items
  27.         match = re.search(r"Operation: new = old (.*)", line)
  28.         if match:
  29.             operands = tuple([op for op in match.group(1).split(" ")])
  30.             monkey["operation"] = operands
  31.         match = re.search(r"Test: divisible by (\d+)", line)
  32.         if match:
  33.             monkey["test"] = [int(match.group(1))]
  34.         match = re.search(r"If true: throw to monkey (\d+)", line)
  35.         if match:
  36.             monkey["test"].append(match.group(1))
  37.         match = re.search(r"If false: throw to monkey (\d+)", line)
  38.         if match:
  39.             monkey["test"].append(match.group(1))
  40.             monkey["test"] = tuple(monkey["test"])
  41.     for monkey in monkeys:
  42.         monkey["count"] = 0
  43.     return monkeys
  44.  
  45.  
  46. def inspect(item: int, operation: str, value: str, divisor: bool = True) -> int:
  47.     """Do operation on item; return its solution"""
  48.     if value == "old":
  49.         value = item
  50.     match operation:
  51.         case "+":
  52.             item = item + int(value)
  53.         case "*":
  54.             item = item * int(value)
  55.     if divisor:
  56.         return item // 3
  57.     else:
  58.         return item
  59.  
  60.  
  61. def test_monkey(item: int, test: int, dest1: str, dest2: str) -> int:
  62.     """Check if item meets monkey test; return number of monkey to throw to"""
  63.     if item % test == 0:
  64.         return int(dest1)
  65.     else:
  66.         return int(dest2)
  67.  
  68.  
  69. def part1(monkeys: Monkeys) -> int:
  70.     """Solve part 1"""
  71.     for _ in range(20):
  72.         for monkey in monkeys:
  73.             monkey["starting_items"] = [
  74.                 inspect(item, *monkey["operation"]) for item in monkey["starting_items"]
  75.             ]
  76.             for item in monkey["starting_items"]:
  77.                 dest: int = test_monkey(item, *monkey["test"])
  78.                 monkeys[dest]["starting_items"].append(item)
  79.             monkey["count"] += len(monkey["starting_items"])
  80.             monkey["starting_items"] = []
  81.     counts: list[int] = [monkey["count"] for monkey in monkeys]
  82.     first: int
  83.     second: int
  84.     first, second = sorted(counts)[-2:]
  85.     return first * second
  86.  
  87.  
  88. def part2(monkeys: Monkeys) -> int:
  89.     """Solve part 2"""
  90.     tests: list[int] = [monkey["test"][0] for monkey in monkeys]
  91.     supermodulo: int = prod(tests)
  92.     for _ in range(10000):
  93.         for monkey in monkeys:
  94.             monkey["starting_items"] = [
  95.                 inspect(item, *monkey["operation"], False)
  96.                 for item in monkey["starting_items"]
  97.             ]
  98.             for item in monkey["starting_items"]:
  99.                 item %= supermodulo
  100.                 dest = test_monkey(item, *monkey["test"])
  101.                 monkeys[dest]["starting_items"].append(item)
  102.             monkey["count"] += len(monkey["starting_items"])
  103.             monkey["starting_items"] = []
  104.     counts: list[int] = [monkey["count"] for monkey in monkeys]
  105.     first: int
  106.     second: int
  107.     first, second = sorted(counts)[-2:]
  108.     return first * second
  109.  
  110.  
  111. def solve(puzzle_input: str) -> tuple[int, int]:
  112.     """Solve the puzzle for the given input"""
  113.     data: Monkeys = parse(puzzle_input)
  114.     solution1: int = part1(data)  # Correct answer was 55216 (with my data)
  115.     data2: Monkeys = parse(puzzle_input)
  116.     solution2: int = part2(data2)  # Correct answer was 12848882750 (with my data)
  117.  
  118.     return solution1, solution2
  119.  
  120.  
  121. if __name__ == "__main__":
  122.     for path in sys.argv[1:]:
  123.         print(f"{path}:")
  124.         puzzle_input = pathlib.Path(path).read_text().strip()
  125.         solutions = solve(puzzle_input)
  126.         print("\n".join(str(solution) for solution in solutions))
  127.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement