-1

I've created a virtual chessboard with 64 spaces formed as a nested array. I'm trying to go through each spot and check if the value of the spot is zero. I'm using np.where to get the indexes of the spot, however eventually np.where starts to return multiple values which throws an error. How can I get it to return ONLY the indexes of the spot that I am currently on?

    while chessboard[result[0], result[1]] != 0:
    for row in chessboard:
        for spot in row:
            if spot == 0:
                location = np.where(chessboard == spot)
                print(location)
                for move in possible_moves:
                    if (location[0] + move[0]) < 0 or (location[1] + move[1]) < 0 or (location[0] + move[0]) > 7 or (location[1] + move[1]) > 7:
                        continue
                    else:
                        chessboard_updated[location[0] + move[0], location[1] + move[1]] = 0

    chessboard = chessboard_updated
    counter += 1

Eventually I get the error

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

because

location

returns

(array([5, 6, 7], dtype=int32), array([1, 2, 0], dtype=int32))

it returns 5,6,7 instead of just 1 value

Thank you.

  • `np.where(chessboard, 0)` returns *all* indices where the array has a value of 0. Since you set some values to 0 in the loop, eventually this will be more than one index. I‘m not sure why that surprises you. – mkrieger1 Jul 19 '20 at 23:05
  • `where` gives a tuple of 2 arrays, `row` and `col` indices. It found 2 points. `chessboard[location]` should return `[0,0,0]`, the 3 zeros on the board. – hpaulj Jul 19 '20 at 23:09
  • You already know the current row index, it is `row`. For the column index you could use `enumerate` when iterating over the row. – mkrieger1 Jul 19 '20 at 23:09
  • The 3 0's are at (5,1), (6,2) and (7,0). You can get those with `np.transpose(location)` (or `np.argwhere`). – hpaulj Jul 19 '20 at 23:54

1 Answers1

0

To summarize the comments.

In [102]: arr = np.random.randint(0,4,(5,5))                                                         
In [103]: arr                                                                                        
Out[103]: 
array([[1, 2, 1, 0, 2],
       [1, 2, 3, 0, 0],
       [3, 0, 1, 1, 1],
       [0, 0, 3, 3, 0],
       [1, 3, 2, 0, 1]])

np.where returns a tuple of arrays telling us where the condition is True:

In [104]: np.nonzero(arr==0)                                                                         
Out[104]: (array([0, 1, 1, 2, 3, 3, 3, 4]), array([3, 3, 4, 1, 0, 1, 4, 3]))

That tuple can be used directly to index the source array:

In [105]: arr[_]                                                                                     
Out[105]: array([0, 0, 0, 0, 0, 0, 0, 0])

We can convert that tuple into a 2d array with np.transpose (or argwhere):

In [106]: np.argwhere(arr==0)                                                                        
Out[106]: 
array([[0, 3],
       [1, 3],
       [1, 4],
       [2, 1],
       [3, 0],
       [3, 1],
       [3, 4],
       [4, 3]])

but that can't be use directly to index the array. We either have to iterate or use the columns as indices:

In [107]: [arr[tuple(ij)] for ij in _106]                                                               
Out[107]: [0, 0, 0, 0, 0, 0, 0, 0]
In [108]: arr[_106[0], _106[1]]                                                                      
Out[108]: array([2, 3])
In [109]: arr[_106[:,0], _106[:,1]]                                                                  
Out[109]: array([0, 0, 0, 0, 0, 0, 0, 0])

If the condition array had only one True, then the where tuple would be something like:

(np.array([0]), np.array([4]))

two size 1 arrays.

You get the ambiguity error because you found multiple True points.

if (location[0] + move[0]) < 0 or (location[1] + move[1]) < 0 ...

location[0] is an array with several values. (location[0] + move[0]) < 0 is then a boolean array with more than 1 value. That can't be used in a Python if or or context, both of which expect only one True/False value.

hpaulj
  • 221,503
  • 14
  • 230
  • 353