osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Conway's game of Life, just because.


Le 07/05/2019 ? 05:31, Paul Rubin a ?crit?:
> #!/usr/bin/python3
> from itertools import chain
> 
> def adjacents(cell):            # generate coordinates of cell neighbors
>      x, y = cell                 # a cell is just an x,y coordinate pair
>      return ((x+i,y+j) for i in [-1,0,1] for j in [-1,0,1] if i or j)
> 
> def update(living):             # living = currently living set of cells
>      def ncount(cell):           # number of living neighbors of cell
>          return sum(1 for c in adjacents(cell) if c in living)
>      def uninhabitable(cell):    # check if occupied cell should die
>          return not(2 <= ncount(cell) <= 3)
>      def fertile(cell):          # check if empty cell should have a birth
>          return ncount(cell) == 3
> 
>      # get set of cells (living or not) that are adjacent to some living cell
>      neighbors = set(chain.from_iterable(adjacents(c) for c in living))
> 
>      frontier = neighbors - living # the empty cells adjacent to living ones
>      births = set(filter(fertile, frontier)) # are where births can happen
>      deaths = set(filter(uninhabitable, living))
>      return (living - deaths) | births
> 
> if __name__ == '__main__':
>      r = set([(0,0),(0,1),(0,2),(1,2),(-1,1)])  # R-pentomino
>      for i in range(1,1110):   # it should stabilize at generation 1104
>          print (i,len(r))      # show generation number and population
>          r = update(r)
> 


I found in a Game Of Life program (not mine) a very clever method to
update a board of cell.

It worths seeing it.

X is a numpy 2D ndarray

def evolve(X):
     ''' Evolves a board of Game of Life for one turn '''
     # Dead cells as a boundary condition
     # Count neighbours
     # Alive if 3 neighbours or 2 neighbours and already alive

     Xi = X.astype(int)
     neigh = np.zeros(Xi.shape)

     neigh[1:-1,1:-1] = (Xi[:-2,:-2]  + Xi[:-2,1:-1] + Xi[:-2,2:] +
                         Xi[1:-1,:-2] +                Xi[1:-1,2:]  +
                         Xi[2:,:-2]   + Xi[2:,1:-1]  + Xi[2:,2:])

     return np.logical_or(neigh==3,np.logical_and(Xi==1,neigh==2))