101 lines
3.5 KiB
Python
101 lines
3.5 KiB
Python
def parse_instructions(file_path):
|
|
"""Parse instructions from the given file."""
|
|
try:
|
|
with open(file_path, 'r') as file:
|
|
instructions = [line.strip().split() for line in file.readlines()]
|
|
print(f"Parsed {len(instructions)} instructions from {file_path}")
|
|
return instructions
|
|
except Exception as e:
|
|
print(f"Error reading file {file_path}: {e}")
|
|
raise
|
|
|
|
def apply_instruction(grid, position, direction, steps):
|
|
"""Apply a single instruction to the grid and update the position."""
|
|
deltas = {'U': (0, -1), 'D': (0, 1), 'L': (-1, 0), 'R': (1, 0)}
|
|
dx, dy = deltas[direction]
|
|
for _ in range(steps):
|
|
position = (position[0] + dx, position[1] + dy)
|
|
grid.add(position)
|
|
#print(f"Moved {direction} to {position}")
|
|
return position
|
|
|
|
def create_path(instructions):
|
|
"""Create the path based on the instructions."""
|
|
grid = set()
|
|
position = (0, 0)
|
|
grid.add(position)
|
|
|
|
for instruction in instructions:
|
|
direction, steps = instruction[0], int(instruction[1])
|
|
print(f"Applying instruction: {direction} {steps}")
|
|
position = apply_instruction(grid, position, direction, steps)
|
|
|
|
return grid
|
|
|
|
def flood_fill(grid, bounds):
|
|
"""Perform flood-fill to find cells outside the path."""
|
|
filled = set()
|
|
to_fill = [(bounds[0], y) for y in range(bounds[2], bounds[3] + 1)] \
|
|
+ [(bounds[1], y) for y in range(bounds[2], bounds[3] + 1)] \
|
|
+ [(x, bounds[2]) for x in range(bounds[0], bounds[1] + 1)] \
|
|
+ [(x, bounds[3]) for x in range(bounds[0], bounds[1] + 1)]
|
|
|
|
while to_fill:
|
|
x, y = to_fill.pop()
|
|
if (x, y) in filled or (x, y) in grid:
|
|
continue
|
|
filled.add((x, y))
|
|
if x > bounds[0]: to_fill.append((x - 1, y))
|
|
if x < bounds[1]: to_fill.append((x + 1, y))
|
|
if y > bounds[2]: to_fill.append((x, y - 1))
|
|
if y < bounds[3]: to_fill.append((x, y + 1))
|
|
|
|
return filled
|
|
|
|
def calculate_area(grid):
|
|
"""Calculate the area inside the loop."""
|
|
min_x = min(grid, key=lambda x: x[0])[0]
|
|
max_x = max(grid, key=lambda x: x[0])[0]
|
|
min_y = min(grid, key=lambda x: x[1])[1]
|
|
max_y = max(grid, key=lambda x: x[1])[1]
|
|
bounds = (min_x, max_x, min_y, max_y)
|
|
|
|
outside_area = flood_fill(grid, bounds)
|
|
total_area = (max_x - min_x + 1) * (max_y - min_y + 1)
|
|
inside_area = total_area - len(outside_area)
|
|
|
|
return inside_area
|
|
|
|
def run_test(test_file):
|
|
"""Run the algorithm with test input."""
|
|
try:
|
|
instructions = parse_instructions(test_file)
|
|
grid = create_path(instructions)
|
|
area = calculate_area(grid)
|
|
assert area == 62, f"Test failed. Expected 62 but got {area} with grid {grid}"
|
|
print("Test passed successfully.")
|
|
return True
|
|
except AssertionError as e:
|
|
print(f"Assertion Error: {e}")
|
|
return False
|
|
|
|
def main():
|
|
"""Main function to run the puzzle solution."""
|
|
test_file = "../test.txt"
|
|
input_file = "../input.txt"
|
|
|
|
# Run test
|
|
if run_test(test_file):
|
|
# Process actual puzzle input
|
|
try:
|
|
instructions = parse_instructions(input_file)
|
|
grid = create_path(instructions)
|
|
area = calculate_area(grid)
|
|
print(f"Puzzle result (area): {area}")
|
|
except Exception as e:
|
|
print(f"Error during puzzle execution: {e}")
|
|
else:
|
|
print("Test failed. Halting execution.")
|
|
|
|
if __name__ == "__main__":
|
|
main() |