Advertisement
Guest User

Untitled

a guest
Dec 15th, 2024
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.48 KB | None | 0 0
  1. from pathlib import Path
  2.  
  3.  
  4. def parse_data(file_name):
  5.     file_path = Path(__file__).resolve().parent / f"{file_name}.txt"
  6.     wall, box, instructions = set(), set(), []
  7.     robot = 0
  8.  
  9.     with file_path.open() as f:
  10.         map_data, instruction_data = f.read().split("\n\n")
  11.  
  12.         for row_idx, row in enumerate(map_data.split()):
  13.             for col_idx, item in enumerate(row.strip()):
  14.                 position = col_idx + row_idx * 1j
  15.                 if item == "#":
  16.                     wall.add(position)
  17.                 elif item == "O":
  18.                     box.add(position)
  19.                 elif item == "@":
  20.                     robot = position
  21.  
  22.         instructions = [
  23.             {"<": -1, "^": -1j, ">": 1, "v": 1j}[d]
  24.             for d in instruction_data.strip()
  25.             if d in "<^>v"
  26.         ]
  27.  
  28.     return wall, box, instructions, robot
  29.  
  30.  
  31. def simulate(wall, box, instructions, robot):
  32.     box_positions = box.copy()
  33.     robot_position = robot
  34.  
  35.     for move in instructions:
  36.         stack = [robot_position]
  37.         current_boxes, new_box_positions = set(), set()
  38.  
  39.         while stack:
  40.             current_position = stack.pop()
  41.             next_position = current_position + move
  42.  
  43.             if next_position in wall:
  44.                 break
  45.  
  46.             if next_position in box_positions:
  47.                 stack.append(next_position)
  48.                 current_boxes.add(next_position)
  49.                 new_box_positions.add(next_position + move)
  50.         else:
  51.             robot_position += move
  52.             box_positions = (box_positions - current_boxes) | new_box_positions
  53.  
  54.     return robot_position, box_positions
  55.  
  56.  
  57. def increase_wide(walls, boxes, robot):
  58.     robot += robot.real
  59.     new_wall = {w.real + w + offset for w in walls for offset in (0, 1)}
  60.     box_left = {b.real + b for b in boxes}
  61.     box_right = {b.real + b + 1 for b in boxes}
  62.     return new_wall, box_left, box_right, robot
  63.  
  64.  
  65. def simulate_new(wall, box_left, box_right, instructions, robot):
  66.     box_positions_left = box_left.copy()
  67.     box_positions_right = box_right.copy()
  68.     robot_position = robot
  69.  
  70.     for move in instructions:
  71.         stack = [robot_position]
  72.         current_boxes_left, new_box_positions_left = set(), set()
  73.         current_boxes_right, new_box_positions_right = set(), set()
  74.  
  75.         while stack:
  76.             current_position = stack.pop()
  77.             next_position = current_position + move
  78.             if next_position in wall:
  79.                 break
  80.  
  81.             if (
  82.                 next_position in box_positions_left
  83.                 and next_position + 1 in box_positions_right
  84.             ):
  85.                 if move != 1:
  86.                     stack.append(next_position)
  87.                 stack.append(next_position + 1)
  88.                 current_boxes_left.add(next_position)
  89.                 current_boxes_right.add(next_position + 1)
  90.                 new_box_positions_left.add(next_position + move)
  91.                 new_box_positions_right.add(next_position + 1 + move)
  92.  
  93.             if (
  94.                 next_position in box_positions_right
  95.                 and next_position - 1 in box_positions_left
  96.             ):
  97.                 if move != -1:
  98.                     stack.append(next_position)
  99.                 stack.append(next_position - 1)
  100.                 current_boxes_left.add(next_position - 1)
  101.                 current_boxes_right.add(next_position)
  102.                 new_box_positions_left.add(next_position - 1 + move)
  103.                 new_box_positions_right.add(next_position + move)
  104.         else:
  105.             robot_position += move
  106.             box_positions_left = (
  107.                 box_positions_left - current_boxes_left
  108.             ) | new_box_positions_left
  109.             box_positions_right = (
  110.                 box_positions_right - current_boxes_right
  111.             ) | new_box_positions_right
  112.  
  113.     return robot_position, box_positions_left, box_positions_right
  114.  
  115.  
  116. def main():
  117.     file_name = "data"
  118.     wall, box, instructions, robot = parse_data(file_name)
  119.     final_robot, final_boxes = simulate(wall, box, instructions, robot)
  120.     print(sum((int(pos.real) + 100 * int(pos.imag)) for pos in final_boxes))
  121.  
  122.     new_wall, box_left, box_right, new_robot = increase_wide(wall, box, robot)
  123.     final_robot_2, box_left, box_right = simulate_new(
  124.         new_wall, box_left, box_right, instructions, new_robot
  125.     )
  126.     print(sum((int(pos.real) + 100 * int(pos.imag)) for pos in box_left))
  127.  
  128.  
  129. if __name__ == "__main__":
  130.     main()
  131.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement