JonathanGupton

Advent of Code 2024 - Day 05 - Python

Dec 5th, 2024
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.35 KB | None | 0 0
  1. from collections import defaultdict
  2. from collections import deque
  3. from pathlib import Path
  4.  
  5.  
  6. def get_data(filepath: Path) -> str:
  7.     with open(filepath, "r") as f:
  8.         data = f.read()
  9.     return data
  10.  
  11.  
  12. def parse_data(
  13.     input_val: str,
  14. ) -> tuple[dict[int, set[int]], tuple[tuple[int, ...], ...]]:
  15.     rules, updates = input_val.strip().split("\n\n")
  16.     ordering_rules = defaultdict(set)
  17.     for rule in rules.split("\n"):
  18.         before, after = map(int, rule.split("|"))
  19.         ordering_rules[before].add(after)
  20.     update_vals = tuple(
  21.         tuple(map(int, nums.split(","))) for nums in updates.split("\n")
  22.     )
  23.     return ordering_rules, update_vals
  24.  
  25.  
  26. def reverse_order_dict(orders: dict[int, set[int]]) -> dict[int, set[int]]:
  27.     reverse = defaultdict(set)
  28.     for k, v in orders.items():
  29.         for n in v:
  30.             reverse[n].add(k)
  31.     return reverse
  32.  
  33.  
  34. def is_correctly_ordered(
  35.     update: tuple[int, ...], order_rules: dict[int, set[int]]
  36. ) -> bool:
  37.     update_set = set(update)
  38.     for n in update[::-1]:
  39.         update_set.remove(n)
  40.         if not update_set.issubset(order_rules[n]):
  41.             return False
  42.     return True
  43.  
  44.  
  45. def get_middle_page_number(rule: tuple[int, ...]) -> int:
  46.     return rule[len(rule) // 2]
  47.  
  48.  
  49. def re_order_pages(
  50.     rule: tuple[int, ...], orders: dict[int, set[int]]
  51. ) -> tuple[int, ...]:
  52.     rule_set: set[int] = set(rule)
  53.     rule_q: deque[int] = deque(rule)
  54.     reordered: deque[int] = deque()
  55.     while rule_q:
  56.         r = rule_q.popleft()
  57.         rule_set.remove(r)
  58.         if rule_set.issubset(orders[r]):
  59.             reordered.append(r)
  60.             continue
  61.         else:
  62.             rule_set.add(r)
  63.             rule_q.append(r)
  64.     return tuple(reordered)
  65.  
  66.  
  67. def part_a_example_1():
  68.     fp = Path("./example/day05-example-01.txt")
  69.     data = get_data(fp)
  70.     orders, updates = parse_data(data)
  71.     reverse_orders = reverse_order_dict(orders)
  72.     result = 0
  73.     for rule in updates:
  74.         if is_correctly_ordered(rule, reverse_orders):
  75.             result += get_middle_page_number(rule)
  76.     print(result, "= 143")
  77.  
  78.  
  79. def part_a():
  80.     fp = Path("./data/day05.txt")
  81.     data = get_data(fp)
  82.     orders, updates = parse_data(data)
  83.     reverse_orders = reverse_order_dict(orders)
  84.     result = 0
  85.     for rule in updates:
  86.         if is_correctly_ordered(rule, reverse_orders):
  87.             result += get_middle_page_number(rule)
  88.     print(result)
  89.  
  90.  
  91. def part_b_example_1():
  92.     fp = Path("./example/day05-example-01.txt")
  93.     data = get_data(fp)
  94.     orders, updates = parse_data(data)
  95.     reverse_orders = reverse_order_dict(orders)
  96.  
  97.     result = 0
  98.     for rule in updates:
  99.         if not is_correctly_ordered(rule, reverse_orders):
  100.             new_rule = re_order_pages(rule, orders)
  101.             result += get_middle_page_number(new_rule)
  102.     print(result, " = 123")
  103.  
  104.  
  105. def part_b():
  106.     fp = Path("./data/day05.txt")
  107.     data = get_data(fp)
  108.     orders, updates = parse_data(data)
  109.     reverse_orders = reverse_order_dict(orders)
  110.  
  111.     result = 0
  112.     for rule in updates:
  113.         if not is_correctly_ordered(rule, reverse_orders):
  114.             new_rule = re_order_pages(rule, orders)
  115.             result += get_middle_page_number(new_rule)
  116.     print(result)
  117.  
  118.  
  119. if __name__ == "__main__":
  120.     part_a_example_1()
  121.     part_a()
  122.     part_b_example_1()
  123.     part_b()
  124.  
Advertisement
Add Comment
Please, Sign In to add comment