'What is the formula for creating an n-dimensional grid from a 1-dimensional loop?
I'm trying to create a 3D grid of Node types (a custom data-type).
To create a 2D grid, I usually use this formula:
where i is the current iteration in 1D loop, and gridsize is size of one axis of grid
x = i % gridsize,
y = floor(i / gridsize)
For example, in Python:
from math import floor
grid = list()
gridsize = 3 # 3x3 grid
for i in range(gridsize**2):
x = i % gridsize
y = floor(i / gridsize)
grid.append( Node(x, y) )
How can I alter this formula to find x, y, and z coordinates for a 3D grid, and is there a general rule for finding coordinates for nD grids?
Solution 1:[1]
x ticks up the fastest, incrementing by 1 every time i increments, and wraps around when it reaches gridsize:
x = i % gridsize
y ticks up more slowly, incrementing by 1 every time i increases by gridsize, but also wraps around when it reaches gridsize:
y = (i // gridsize) % gridsize
z ticks up the slowest, incrementing by 1 every time i increases by gridsize**2, and we don't need it to wrap around:
z = i // gridsize**2
We can generalize this:
x = (i // gridsize**0) % gridsize
y = (i // gridsize**1) % gridsize
z = (i // gridsize**2) % gridsize
I'm sure you see the pattern here.
Solution 2:[2]
Afer writing out a table of x, y and z values for a 3x3x3 grid, I figured this out:
For a cubic 3D¹ grid
x = i % gs
y = floor(i / gs) % gs
z = floor(i / gs²)
where i is the current iteration, and gs is length of one axis.
With a bit of extrapolation, here's a formula2 for an nD grid:
cn = floor(i / gsn-1) % gs
For example:
x = floor( i / gs? ) % gs # 1D
y = floor( i / gs¹ ) % gs # 2D
z = floor( i / gs² ) % gs # 3D
a = floor( i / gs³ ) % gs # 4D
etc.
NOTE:
- The
xvalue can be simplified toi % gsbecausei/gs0 % gs=>i/1 % gs=>i % gs. Likewise, we can remove the% gsfrom the calculation of thezvalue, because the loop should never go overgs3 - This formula only works for cubic grids (ie. grids whose axes all have the same number of points on them - 2x2x2x2, 5x5x5, etc.). 3x4x5 grids, for example, require a different formula.
Solution 3:[3]
I wouldn't use a formula but just this:
r = range(gridsize)
grid = [Node(x, y, z) for z in r for y in r for x in r]
Or with an arbitrary dimension, using itertools.product:
grid = [Node(*p[::-1]) for p in product(range(gridsize), repeat=griddim)]
If you don't mind the order of the nodes, you can leave out the [::-1] or also use itertools.starmap:
grid = list(starmap(Node, product(range(gridsize), repeat=griddim)))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Thomas |
| Solution 2 | |
| Solution 3 | Kelly Bundy |
