You just need to iterate over the Cartesian power of the set {-1, 0, 1} to N to form the indices relative to the current one, being careful to discard the all-zeros combination (which would correspond to the current element):
algorithm neighbors(N : positive integer,
index : N-tuple of integers)
neighbors_list := empty list
for relative_index in cartesian_power({-1, 0, 1}, N) do
if not (relative_index is all zeros then)
new_index := [index[i] + relative_index[i] for i in 1..N]
neighbors_list := append(neighbors_list, new_index)
end
loop
return neighbors_list
Note that this can be lazily evaluated when possible and necessary. The Cartesian power can as well be implemented in a non-recursive manner:
algorithm cartesian_power(s : set, N : positive integer)
result := list(empty list)
repeat N times
result_step= empty list
for res in result do
for elem in s do
new_res := append(res, s)
result_step := append(result_step, new_res)
loop
loop
result := result_step
loop
return result
You could also lazy-evaluate this algorithm, although it's a bit more complicated because you would have to generate the elements created in the last iteration of the outermost loop.
These algorithms do not take into account things like index bounds or other constraints, so you may need to add additional logic depending on the case, but the core idea is the same.
Here is an example implementation as a Python generator:
from itertools import product
def neighbors(index):
N = len(index)
for relative_index in product((-1, 0, 1), repeat=N):
if not all(i == 0 for i in relative_index):
yield tuple(i + i_rel for i, i_rel in zip(index, relative_index))
print(list(neighbors((1, 2)))
>>> [(0, 1), (0, 2), (0, 3), (1, 1), (1, 3), (2, 1), (2, 2), (2, 3)]
print(list(neighbors((1, 2, 3)))
>>> [(0, 1, 2),
(0, 1, 3),
(0, 1, 4),
(0, 2, 2),
(0, 2, 3),
(0, 2, 4),
(0, 3, 2),
(0, 3, 3),
(0, 3, 4),
(1, 1, 2),
(1, 1, 3),
(1, 1, 4),
(1, 2, 2),
(1, 2, 4),
(1, 3, 2),
(1, 3, 3),
(1, 3, 4),
(2, 1, 2),
(2, 1, 3),
(2, 1, 4),
(2, 2, 2),
(2, 2, 3),
(2, 2, 4),
(2, 3, 2),
(2, 3, 3),
(2, 3, 4)]
Obviously I am cheating here because I am using a Python builtin function to compute the Cartesian power. However, if you go to the documentation of itertools.product
you will see a Python implementation of the algorithm I wrote above.