Advertisement
JonathanGupton

Advent of Code 2024 - Day 14 - Python

Dec 15th, 2024
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.61 KB | None | 0 0
  1. from collections import defaultdict
  2. import re
  3. import numpy as np
  4.  
  5.  
  6. def parse_data(fp: str) -> np.ndarray:
  7.     output = []
  8.     pattern = r"p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)"
  9.     with open(fp, "r") as f:
  10.         for line in f.readlines():
  11.             match = re.match(pattern, line)
  12.             p_x, p_y, v_x, v_y = map(int, match.groups())
  13.             output.append((p_x, p_y, v_x, v_y))
  14.     arr = np.array(output)
  15.     return arr
  16.  
  17.  
  18. def create_robot_str(configuration: np.ndarray, dims: tuple[int, int]) -> str:
  19.     width, height = dims
  20.     field = [["." for x in range(width)] for _ in range(height)]
  21.     positions = defaultdict(int)
  22.     for x, y in configuration[:, :2]:
  23.         positions[(x, y)] += 1
  24.     for (x, y), v in positions.items():
  25.         field[y][x] = str(v)
  26.     output_str = "\n".join(["".join(line) for line in field])
  27.     return output_str
  28.  
  29.  
  30. def print_robots(configuration: np.ndarray, dims: tuple[int, int]) -> None:
  31.     output_str = create_robot_str(configuration, dims)
  32.     print(output_str, sep="\r" * len(output_str))
  33.  
  34.  
  35. def advance_robots(robots: np.ndarray, dims: tuple[int, int]) -> np.ndarray:
  36.     width, height = dims
  37.     robots[:, 0] += robots[:, 2]
  38.     robots[:, 1] += robots[:, 3]
  39.     robots[robots[:, 0] < 0, 0] += width
  40.     robots[robots[:, 0] >= width, 0] -= width
  41.     robots[robots[:, 1] < 0, 1] += height
  42.     robots[robots[:, 1] >= height, 1] -= height
  43.     return robots
  44.  
  45.  
  46. def compute_quadrant_census(
  47.     robots: np.ndarray, dims: tuple[int, int]
  48. ) -> tuple[int, int, int, int]:
  49.     width, height = dims
  50.     q_width, q_height = width // 2, height // 2
  51.     top_half = robots[:, 1] < q_height
  52.     bottom_half = robots[:, 1] > q_height
  53.     left_half = robots[:, 0] < q_width
  54.     right_half = robots[:, 0] > q_width
  55.     top_left = robots[top_half & left_half]
  56.     top_right = robots[top_half & right_half]
  57.     bottom_left = robots[bottom_half & left_half]
  58.     bottom_right = robots[bottom_half & right_half]
  59.     return len(top_left), len(top_right), len(bottom_left), len(bottom_right)
  60.  
  61.  
  62. def example_a():
  63.     fp = "./example/day14-example02.txt"
  64.     robots = parse_data(fp)
  65.     dimensions = (11, 7)
  66.     print_robots(robots, dimensions)
  67.     for i in range(5):
  68.         robots = advance_robots(robots, dimensions)
  69.         print(i + 1)
  70.         print_robots(robots, dimensions)
  71.  
  72.     fp = "./example/day14-example01.txt"
  73.     robots = parse_data(fp)
  74.     dimensions = (11, 7)  # 11 wide, 7 tall
  75.     for _ in range(100):
  76.         robots = advance_robots(robots, dimensions)
  77.     t_l, t_r, b_l, b_r = compute_quadrant_census(robots, dimensions)
  78.     safety_factor = t_l * t_r * b_l * b_r
  79.     print(safety_factor)
  80.  
  81.  
  82. def part_a():
  83.     fp = "./data/day14.txt"
  84.     robots = parse_data(fp)
  85.     width = 101
  86.     height = 103
  87.     dimensions = (width, height)
  88.     for _ in range(100):
  89.         robots = advance_robots(robots, dimensions)
  90.     t_l, t_r, b_l, b_r = compute_quadrant_census(robots, dimensions)
  91.     safety_factor = t_l * t_r * b_l * b_r
  92.     print(safety_factor)
  93.  
  94.  
  95. def part_b():
  96.     fp = "./data/day14.txt"
  97.     robots = parse_data(fp)
  98.     width = 101
  99.     height = 103
  100.     dimensions = (width, height)
  101.     iterations = 0
  102.     output_file = "./output/robot_positions.txt"
  103.     with open(output_file, "a") as f:
  104.         for i in range(20000):
  105.             iterations += 1
  106.             robots = advance_robots(robots, dimensions)
  107.             print(iterations, sep="\n")
  108.             robot_str = create_robot_str(robots, dimensions)
  109.             f.write(f"Iteration {iterations}:\n{robot_str}\n\n")
  110.  
  111.  
  112. if __name__ == "__main__":
  113.     example_a()
  114.     part_a()
  115.     part_b()
  116.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement