Image filters are usually used to compute transformations such as blurring and sharpening. We pass a
kernel over every pixel that computes the new image pixel based on its surroundings. For the game of life, if we treat the current state of the board as an image, we can pass a particular filter that will compute the neighbors around each pixel.
This is a remarkably elegant way of representing the transition between states. We can take advantage of the Fast Fourier Transform in image processing libraries to concisely write an implementation of GOL.
Here's my implementation in Julia:
using Base.Graphics using Cairo using Tk using Images # Use an image filter to compute neighbors function evolve(grid) neighbors = imfilter(grid, [1 1 1; 1 9 1; 1 1 1]); ((neighbors .== 11) | (neighbors .== 12) | (neighbors .== 3)) & 1 end # Creates an NxN board for `iter` generations function iterate(N::Int, iter::Int, sparse::Float64 = 0.1) win = Toplevel("Game of Life", N, N) c = Canvas(win) pack(c, expand=true, fill="both") ctx = getgc(c) grid = (rand(N,N) .< sparse) & 1; for i=1:iter grid = evolve(grid) buf = uint32color(grid .* 255) image(ctx,CairoRGBSurface(buf), 0, 0, N, N) reveal(c) Tk.update(); end end # Create a 500x500 board for 500 generations iterate(500,500)
imfilter doesn't necessarily use
fft internally, my next task is to run benchmarks on different ways of computing the neighbors matrix.
The code can be found here, and I'm always open for pull requests!