Jort de Bokx
Jort de Bokx

Reputation: 25

How to 'ignore' an index out of range error in Python

My teacher set me the task to make a Python version of "The Game of Life", So after I got most of the code working. I got stuck on what I suspect would be a rather common problem: The corners and edges don't have 8 neighbors. So using the following code would give me an index out of range exception:

neighbors = (a[x-1][y-1]+a[x-1][y]+a[x-1][y+1]+a[x][y-1]+a[x][y+1]
             +a[x+1][y-1]+a[x+1][y]+a[x+1][y+1])

So instead of using a lot of if statements, I wanted to catch the indexes that are out of range and pass the value 0 instead. How would I attempt to do that?

Upvotes: 0

Views: 9982

Answers (3)

martineau
martineau

Reputation: 123501

I'd replace your long expression with a single function call to something like this:

def neighbors(a, x, y):
    total = 0
    for dx, dy in [(-1, -1), (-1, 0), (-1, 1),
                   ( 0, -1),          ( 0, 1),
                   ( 1, -1), ( 1, 0), ( 1, 1)]:
        try:
            total += a[x+dx][y+dy]
        except IndexError:
            pass
    return total

Since there are only eight possible neighbors, for maximum speed you might want to consider unwinding the loop in the above for the following:

def neighbors(a, x, y):
    xm1, xp1, ym1, yp1 = x-1, x+1, y-1, y+1
    total = 0
    try:
        total += a[xm1][ym1]
    except IndexError:
        pass
    try:
        total += a[xm1][y]
    except IndexError:
        pass
    try:
        total += a[xm1][yp1]
    except IndexError:
        pass
    try:
        total += a[x][ym1]
    except IndexError:
        pass
    try:
        total += a[x][yp1]
    except IndexError:
        pass
    try:
        total += a[xp1][ym1]
    except IndexError:
        pass
    try:
        total += a[xp1][y]
    except IndexError:
        pass
    try:
        total += a[xp1][yp1]
    except IndexError:
        pass
    return total

The alternative of creating a function to check each x, y of each location will require nine function calls to compute the same value (and the evaluation of a non-trivial conditional expression each time).

Upvotes: 0

wilkesybear
wilkesybear

Reputation: 528

I would write a helper function that you could call that would either return a value or zero (pseudocode):

def getValue(x, y)
   if x < 0 or y < 0 or x > xbound or y > ybound:
       return 0
   return a[x][y]

Then you can call getValue a bunch of times with different parameters

Upvotes: 0

Eugene Sh.
Eugene Sh.

Reputation: 18371

Make you actual board wider and longer by 2 cells, pad the margins with zeros, and work with indices from 1 to length (or width)-2.

Upvotes: 2

Related Questions