Numpy game of life

The following is a Numpy game of life. All terribly boring, but it's potentially useful to understand how slicing, broadcasting and casting work and to understand what Numpy may be useful for.

#!/usr/bin/python
# By Tom Wright
# Use this code however you like...

""" Numpy game of life."""

import numpy

def iterate(board):
    # find number of neighbours that each square has
    neighbour_count = numpy.zeros(board.shape)
    neighbour_count[1:, 1:] += board[:-1, :-1]
    neighbour_count[1:, :-1] += board[:-1, 1:]
    neighbour_count[:-1, 1:] += board[1:, :-1]
    neighbour_count[:-1, :-1] += board[1:, 1:]
    neighbour_count[:-1, :] += board[1:, :]
    neighbour_count[1:, :] += board[:-1, :]
    neighbour_count[:, :-1] += board[:, 1:]
    neighbour_count[:, 1:] += board[:, :-1]
    
    # a live cell is killed if it has fewer 
    # than 2 or more than 3 neighbours.
    part1 = ((board == 1) & (neighbour_count < 4) & (neighbour_count > 1)) 

    # a new cell forms if a square has exactly three members
    part2 = ((board == 0) & (neighbour_count == 3))

    # cast booleans to integers
    new_board = numpy.cast[numpy.int](part1 | part2)
    return new_board



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


for i in range(100):
    print board
    board = iterate(board)

You can download this here

This is what the equivalent code might look like in python. Notice the extra looping.

# warning - this code has never been run. Also there are probably
# slighlty more succinct ways or doing this.  The key point is that
# more looping is necessary because we can't make the broadcasting do
# looping for us.


def non_numpy_iterate(board):
    neighbour_count = {}
    m, n = max(board)
    directions = ([(0, i) for i in (-1, 1)] + 
                  [(i, j) for i in (-1, 1) for j in (-1, 1)] +
                  [(i, 0) for i in (-1, 1)])
    for x, y in directions:
        for i in range(max(0, x), min(m, m + x)):
            for j in range(max(0, y), min(n, n - y)):
                neighbour_count.setdefault((i, j), 0)
                neighbour_count[i, j] += board[i, j]
    new_board = {}
    for i, j in board:
        state = (board[i, j] and (1 < neighbour_count[i, j] < 4)
                 or not board[i, j] and neighbour_count[i, j] == 3)
        new_board[i, j] == int(state)
    return new_board

You can download this here