user2083363
user2083363

Reputation: 51

Python error with list

I need to replace all elements of the list camp by the respectives output values ​​of a function "counterPosition" that acts on each position of the list

camp = [[True, False, False, False, False, True],
         [False, False, False, False, False, True],
         [True, True, False, True, False, True],
         [True, False, False, False, False, False],
         [False, False, True, False, False, False],
         [False, False, False, False, False, False]]


def counterPosition(x, y):
    bombs = 0
    for i in range(x-1, x+2):
        for j in range(y-1, y+2):
            if i<0 or j<0: continue
            elif camp[i][j] == True:
                bombs += 1
    return bombs

for x in range (len(camp)):
   for y in range (len(camp[x])):
       camp[x][y] = counterPosition(x,y)
print camp

Which gives:

IndexError: list index out of range

Upvotes: 2

Views: 351

Answers (2)

Eric
Eric

Reputation: 97575

Another way to store this data is to use a set:

bombs = {
    (i, j) for i, row in enumerate(camp)
           for j, is_bomb in enumerate(row)
           if is_bomb
}

And then, instead of camp[i][j] == True, do (i, j) in bombs

Upvotes: 0

abarnert
abarnert

Reputation: 365647

The problem is in your counterPosition function. In particular:

for i in range(x-1, x+2):
    for j in range(y-1, y+2):
        …
        elif camp[i][j] == True:

You're passing this values of x ranging from 0 to len(camp)-1. Which means that i ranges from -1 to len(camp)-1+2. So, for example, when you get to the last row, x=5, i will range from -1 to 6. But camp[6] is out of bounds. So you get an IndexError.

You'll have the same problem with y and j, of course.

So, how do you fix that? Well, it depends on what you're trying to do. But, given this line:

if i<0 or j<0: continue

I think what you want is to add this:

elif i>=len(camp) or j>=len(camp[i]): continue

Although really, it would be simpler to eliminate these outside the loop—e.g., for i in range(max(x-1, 0), min(x+2, len(camp)):


Meanwhile, I'm not sure what your program is trying to do, but it looks likesomething kind of Minesweeper-related, yes? If so, I don't think it's going to do what you want even after you fix this. As you replace the True and False values with counts, camp[i][j] == True can never be true for i<=x and j<=y. So, the end result is:

[[2, 2, 2, 1, 3, 2],
 [2, 2, 3, 2, 4, 2],
 [3, 2, 1, 2, 1, 2],
 [1, 3, 2, 3, 1, 2],
 [1, 3, 1, 2, 1, 2],
 [1, 3, 1, 3, 1, 2]]

When I think you may have wanted this:

[[1, 1, 0, 0, 2, 2],
 [3, 3, 2, 1, 4, 3],
 [3, 3, 2, 1, 3, 2],
 [3, 4, 3, 2, 2, 1],
 [1, 2, 1, 1, 0, 0],
 [0, 1, 1, 1, 0, 0]]

That's the number of adjacent bombs at even given square. To get the latter, either iterate over or modify a copy of camp, instead of doing both to the same list. For example:

newcamp = copy.deepcopy(camp)
for x in range (len(camp)):
   for y in range (len(camp[x])):
       newcamp[x][y] = counterPosition(x,y)
print newcamp

Or just:

camp = [[counterPosition(x, y) for y in range(len(camp[x]))] 
        for x in range(len(camp))]
print camp

(Although really, I'd give them different names, like bombcamp and flagcamp or something…)

Upvotes: 2

Related Questions