complex grids are simpler

jan 28, 2026

in my opinion, advent of code is definitely the most exciting part of december (i’d rather not think about what that says about me). every year i pick a theme to complete the puzzles (previous years have included uiua, k, polyglot, etc.) and last year’s theme was concise python. sounds pretty boring, i know, but i did learn some neat tricks along the way. i used to dread the “annoying grid days”, of which my main complaints were:

  1. long-winded bounds checking
  2. nested loops
  3. unergonomic neighbors

indexing

with a typical 2d array setup, the following snippet is commonplace:

if x >= 0 and x < len(GRID[0]) and y >= 0 and y < len(GRID):

the astute pythonistas among yourselves might write it as:

if 0 < x < len(GRID[0]) and 0 < y < len(GRID):

but it still leaves much to be desired. retrieval with a default value might look something like:

v = GRID[y][x] if 0 < x < len(GRID[0]) and 0 < y < len(GRID) else d

which hurts my soul.

dicts as grids

if we instead use a dict as our backing structure, bounds checking becomes trivial:

if (x, y) in GRID:

and retrieval with a default equally so:

v = GRID.get((x, y), d)


our problem of nesting is also solved for free. what was once:

for y, r in enumerate(G):
  for x, v in enumerate(R):

is now simply:

for (x, y), v in G.items():

making it complex

while we’ve solved problems 1 and 2, accessing a cell’s neighbors (which is almost a given in an advent of code grid question) could still use some improvement:

# p = (x, y)
for dx in [-1, 1]:
  for dy in [-1, 1]:
    n = (p[0] + dx, p[1] + dy)

while $\cnums$ acts primarily as a field extension of $\R$, a lesser known purpose is its extension of my happiness throughout the month of december. by using complex numbers as our keys, we get our desired additive behavior for free. behold:

# p = x + y * 1j
for d in [-1, 1, -1j, 1j]:
  n = p + d

the real axis acts as our x, and the imaginary as our y. we can add and subtract points at will now, unrestricted by the shackles of tuples. here are some freebies we get by using dicts and complex keys:

  • euclidean distance: abs(p - q)
  • 90$^\circ$ rotation: p * -i for cw, p * i for ccw
  • multi-updates: GRID |= {p: a, q: b, ...}
  • key transformations: GRID = {f(p): v for p, v in GRID.items()}
  • value transformations: GRID = {p: f(v) for p, v in GRID.items()}

the world is your oyster!

caveats

this method is clearly not the most performant, and your boss certainly does not want to see this in your next code review. i am not responsible for any consequences you face by beginning a grid problem in your next technical interview with “i’ll begin by employing the complex field”.