简体   繁体   中英

Counting Neighbors in Matrix - Conway Game of Life

For each matrix element, I want to add the values of all its neighbor cells.

Starting with my initial array

board = np.array([[0, 1, 1],
                   [0, 1, 0],
                   [1, 0, 0]])

My result should be:

([2,2,2],
 [3,3,3],
 [1,2,1])

I created a function and used a brute force method to find whether or not a cell exists in its surrounding. If it does, add up the values and return the total. I'm not sure if I'm approaching my if statements correctly. It's saying the following error

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

def count_living_neighbors(board):
    count = np.zeros(board.shape, dtype=int)
    #
    # YOUR CODE HERE
    #

    for row in range(len(board)):
        for column in range(len(board[row])):
            total = 0
            if (board[column - 1]).any() in board:
                total += board[row][column-1]
            if (board[column + 1]).any() in board:
                total += board[row][column+1]    
            if (board[row - 1]).any() in board:
                total += board[row-1][column]
            if (board[row + 1]).any() in board:
                total += board[row+1][column]
            if (board[row + 1] and board[column - 1]).any() in board:
                total += board[row+1][column-1]
            if (board[row - 1] and board[column - 1]).any() in board:
                total += board[row-1][column-1]
            if (board[row + 1] and board[column + 1]).any() in board:
                total += board[row+1][column+1]
            if (board[row - 1] and board[column + 1]).any() in board:
                total += board[row+1][column+1]

            count[row][column] = total         

    return count

You can use scipy.signal.convolve with mode='same' :

from scipy import signal

kernel = np.ones((3, 3), dtype=np.int8)
kernel[1, 1] = 0
print(signal.convolve(board, kernel, mode='same'))
[[2 2 2]
 [3 3 3]
 [1 2 1]]

Here kernel looks like this:

array([[1, 1, 1],
       [1, 0, 1],
       [1, 1, 1]], dtype=int8)

and will be the same regardless of the shape of board . Basically, kernel is referring to the positions of the neighbors (relative to the 0 in the center).

Try scipy.signal.convolve2d Something along the lines of

convolve2d( yourMatrix, np.ones((3,3))

Should do the trick

Regarding your code : You may not be very familiar with Python or numpy syntax so I would suggest finding some tutorial to practice the basics. (board[column - 1]).any() will be True if there is any cell alive in the whole column and False other wise. After that you are testing to see if True (or False if all cell in the column are dead) is contained inside the board which will always be True. So your if statements don't make much sense.

To test if one cell in the neihgbourhood is alive , it would look like any of the following if statements :

if board[row-1][column - 1]  ==  1:
if board[row-1, column - 1]   ==  1: 
if board[row-1, column - 1] : #in Python 1 is True and 0 is False

That being said to count the number of cells that are alive around one spot you shouldn't bother with if statements at all, just add all the surrounding values , a dead cell is worth 0 and a live cell worth 1 so only the live cells will show up in the count anyways. And to go further your code will be very slow, you should never use a for loop to iterate over a numpy array, the proper way of doing things is to exploit what is called vectorized operations, that is operations that apply on the whole array at once, for example : board[:,1:]+board[:,:-1] will give you an array that contains the sum the cell on left+cell on the right for each cell where you can compute that sum.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM