In Advent of Code we encounter a lot of grid based puzzles and it’s handy to have some functions (for example in a utility library or in your notes) that print out the grid. You can throw them in whenever you need to visually inspect the grid. This is handy for confirming that you read the input in correctly or to check where the mistake happens.

def print_grid(grid: dict[Tuple[int, int], str]) -> None:
	xs = [x for x,y in grid]
	ys = [y for x,y in grid]
	
	for y in range(min(ys), max(ys)+1):
		for x in range(min(xs), max(xs)+1):
		    print(grid.get((x,y), '#', end="")
		print()

This is the very basic case. We have a sparse dict grid that only contains data for the open/empty positions in the grid. Everything else is blocked. The grid keys are (x, y) pairs.

We find the minimum and maximum values for both x and y coordinates and loop to create a square grid.

If this coordinate exists in the grid, print its value and if it doesn’t, print a default value which in this case is #. We finish each cell print with end="" to avoid newlines and after each row, we print a newline.

If we’re looking at pathfinding puzzles, a helpful adjustment is to allow another argument that contains the path from start to finish:

def print_grid_with_path(
	grid: dict[Tuple[int, int], str],
	path: List[Tuple[int, int]]
) -> None:
	xs = [x for x,y in grid]
	ys = [y for x,y in grid]
	
	for y in range(min(ys), max(ys)+1):
		for x in range(min(xs), max(xs)+1):
			if (x,y) in path:
				print('O')
			else:
			    print(grid.get((x,y), '#', end="")
		print()

Now, if any coordinate is in the path, we mark it as O.