INPUT_FILE = "input.txt" # True for roll of paper floor: list[list[bool]] = [ [ c == '@' for c in line.strip() ] for line in open(INPUT_FILE, 'r').readlines() ] buffer_floor = floor.copy() class iVec2d: x: int y: int def __init__(self, x: int, y: int): self.x = x self.y = y max_y = len(floor) max_x = len(floor[0]) min_y = 0 min_x = 0 def count_neighbors(floor: list[list[bool]], pos: iVec2d) -> int: DIRECTIONS = [ iVec2d(-1, -1), iVec2d(0, -1), iVec2d(1, -1), iVec2d(-1, 0), iVec2d(1, 0), iVec2d(-1, 1), iVec2d(0, 1), iVec2d(1, 1) ] neighbors = 0 for direction in DIRECTIONS: dx, dy = direction.x, direction.y new_x = pos.x + dx new_y = pos.y + dy if new_x >= max_x or new_x < min_x: continue if new_y >= max_y or new_y < min_y: continue if floor[new_y][new_x]: neighbors += 1 return neighbors total_moveable_rolls = 0 while True: moveable_rolls = 0 # Count Moveable Rolls for y in range(len(floor)): for x in range(len(floor[0])): pos = iVec2d(x, y) if floor[pos.y][pos.x]: if count_neighbors(floor, pos) < 4: moveable_rolls += 1 print('x', end='') buffer_floor[pos.y][pos.x] = False else: print('@', end='') else: print('.', end='') print() if moveable_rolls == 0: break total_moveable_rolls += moveable_rolls # Swap buffers floor = buffer_floor.copy() print(f'Moveable Rolls: {total_moveable_rolls}')