from __future__ import division

import itertools


def get_offsets(span):
    """
    Get matrix offsets for a square of distance `span`.
    """
    if span < 0:
        raise ValueError('Cannot return neighbours for negative distance')

    all_offsets = set(itertools.product([x for x in range(-span, span + 1)], repeat=2))
    if span >= 1:
        inner_offsets = set(itertools.product([x for x in range(-(span - 1), span)], repeat=2))
    else:
        inner_offsets = set()
    return all_offsets - inner_offsets


def find_neighbours_2D(array, start, span):
    """
    Return neighbours in a 2D array, given a start point and range.
    """
    x, y = start  # Start coords
    rows = len(array)  # How many rows
    cols = len(array[0])  # Assume square matrix
    offsets = get_offsets(span)
    print(offsets)
    neighbours = set()
    for dx, dy in offsets:
        i = max(0, min(x + dx, rows))
        j = max(0, min(y + dy, cols))
        neighbours.add((i, j))
    return neighbours


def new(size, value=None):
    """ Initialize a new square matrix. """
    return [[value] * size for _ in range(size)]


@@ -635,16 +635,71 @@
 d range.
+%0A%0A    Checks array bounds so we don't get index errors.
 %0A    %22%22%22
@@ -856,27 +856,8 @@
 an)%0A
-    print(offsets)%0A
     
@@ -918,71 +918,151 @@
 i = 
-max(0, min(x + dx, rows))%0A        j = max(0, min(y + dy, cols))
+x + dx%0A        j = y + dy%0A        if i %3C 0 or i %3E= rows or j %3C 0 or j %3E= cols:%0A            continue  # Don't add coords outside of array bounds
 %0A   

Fix find_neighbours_2D to ignore out of bounds points