The Challenge: Write the shortest program that implements John H. Conway's Game of Life cellular automaton. [link]

EDIT: After about a week of competition, I have selected a victor: pdehaan, for managing to beat the Matlab solution by one character with perl.

For those who haven't heard of Game of Life, you take a grid (ideally infinite) of square cells. Cells can be alive (filled) or dead (empty). We determine which cells are alive in the next step of time by applying the following rules:

  1. Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  2. Any live cell with more than three live neighbours dies, as if by overcrowding.
  3. Any live cell with two or three live neighbours lives on to the next generation.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

Your program will read in a 40x80 character ASCII text file specified as a command-line argument, as well as the number of iterations (N) to perform. Finally, it will output to an ASCII file out.txt the state of the system after N iterations.

Here is an example run with relevant files:

in.txt:

................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
..................................XX............................................
..................................X.............................................
.......................................X........................................
................................XXXXXX.X........................................
................................X...............................................
.................................XX.XX...XX.....................................
..................................X.X....X.X....................................
..................................X.X......X....................................
...................................X.......XX...................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................

Iterate 100 times:

Q:\>life in.txt 100

Resultant Output (out.txt)

................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
..................................XX............................................
..................................X.X...........................................
....................................X...........................................
................................XXXXX.XX........................................
................................X.....X.........................................
.................................XX.XX...XX.....................................
..................................X.X....X.X....................................
..................................X.X......X....................................
...................................X.......XX...................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................

The Rules:

  • You need to use file I/O to read/write the files.
  • You need to accept an input file and the number of iterations as arguments
  • You need to generate out.txt (overwrite if it exists) in the specified format
  • You don't need to deal with the edges of the board (wraparound, infinite grids .etc)
  • EDIT: You do need to have newlines in your output file.

The winner will be determined by character count.

Good luck!


Solution 1:

Mathematica - 179 163 154 151 chars

    a = {2, 2, 2};
    s = Export["out.txt", 
       CellularAutomaton[{224, {2, {a, {2, 1, 2}, a}}, {1,1}}, 
                (ReadList[#1, Byte, RecordLists → 2>1] - 46)/ 42, #2]〚#2〛
       /. {0 → ".", 1 → "X"}, "Table"] &
Spaces added for readability

Invoke with

    s["c:\life.txt", 100]

Animation:

alt text

You can also get a graph of the mean population over time:

alt text

A nice pattern for generating gliders from Wikipedia

aa

AFAIK Mathematica uses a Cellular Automaton to generate random numbers using Rule 30.

Solution 2:

MATLAB 7.8.0 (R2009a) - 174 171 161 150 138 131 128 124 characters

Function syntax: (124 characters)

Here's the easier-to-read version (with unnecessary newlines and whitespace added for better formatting):

function l(f,N),
  b=char(importdata(f))>46;
  for c=1:N,
    b=~fix(filter2(ones(3),b)-b/2-3);
  end;
  dlmwrite('out.txt',char(b*42+46),'')

And here's how the program is run from the MATLAB Command Window:

l('in.txt',100)

Command syntax: (130 characters)

After a comment about calling functions with a command syntax, I dug a little deeper and found out that MATLAB functions can in fact be invoked with a command-line format (with some restrictions). You learn something new every day!

function l(f,N),
  b=char(importdata(f))>46;
  for c=1:eval(N),
    b=~fix(filter2(ones(3),b)-b/2-3);
  end;
  dlmwrite('out.txt',char(b*42+46),'')

And here's how the program is run from the MATLAB Command Window:

l in.txt 100


Additional Challenge: Tweetable GIF maker - 136 characters

I thought for fun I'd see if I could dump the output to a GIF file instead of a text file, while still keeping the character count below 140 (i.e. "tweetable"). Here's the nicely-formatted code:

function l(f,N),
  b=char(importdata(f))>46;
  k=ones(3);
  for c=1:N+1,
    a(:,:,:,c)=kron(b,k);
    b=~fix(filter2(k,b)-b/2-3);
  end;
  imwrite(~a,'out.gif')

Although IMWRITE is supposed to create a GIF that loops infinitely by default, my GIF is only looping once. Perhaps this is a bug that has been fixed in newer versions of MATLAB. So, to make the animation last longer and make the evolution steps easier to see, I left the frame delay at the default value (which seems to be around half a second). Here's the GIF output using the Gosper Glider Gun pattern:

alt text


Improvements

  • Update 1: Changed the matrix b from a logical (i.e. "boolean") type to a numerical one to get rid of a few conversions.
  • Update 2: Shortened the code for loading the file and used the function MAGIC as a trick to create the convolution kernel in fewer characters.
  • Update 3: Simplified the indexing logic, replaced ~~b+0 with b/42, and replaced 'same' with 's' as an argument to CONV2 (and it surprisingly still worked!).
  • Update 4: I guess I should have searched online first, since Loren from The MathWorks blogged about golfing and the Game of Life earlier this year. I incorporated some of the techniques discussed there, which required me to change b back to a logical matrix.
  • Update 5: A comment from Aslak Grinsted on the above mentioned blog post suggests an even shorter algorithm for both the logic and performing the convolution (using the function FILTER2), so I "incorporated" (read "copied") his suggestions. ;)
  • Update 6: Trimmed two characters from the initialization of b and reworked the logic in the loop to save 1 additional character.
  • Update 7: Eric Sampson pointed out in an e-mail that I could replace cell2mat with char, saving 4 characters. Thanks Eric!

Solution 3:

Ruby 1.9 - 189 178 159 155 153 chars

f,n=$*
c=IO.read f
n.to_i.times{i=0;c=c.chars.map{|v|i+=1
v<?.?v:('...X'+v)[[83,2,-79].map{|j|c[i-j,3]}.to_s.count ?X]||?.}*''}
File.new('out.txt',?w)<<c

Edit: Handles newlines with 4 chars less.
Can remove 7 more (v<?.?v:) if you allow it to clobber newlines when the live cells reach the edges.

Solution 4:

perl, 127 129 135 chars

Managed to strip off a couple more characters...

$/=pop;@b=split'',<>;map{$n=-1;@b=map{++$n;/
/?$_:($t=grep/X/,@b[map{$n+$_,$n-$_}1,80..82])==3|$t+/X/==3?X:'.'}@b}1..$/;print@b

Solution 5:

Python - 282 chars

might as well get the ball rolling...

import sys
_,I,N=sys.argv;R=range(3e3);B=open(I).read();B=set(k for k in R if'A'<B[k])
for k in R*int(N):
 if k<1:b,B=B,set()
 c=sum(len(set((k+o,k-o))&b)for o in(1,80,81,82))
 if(c==3)+(c==2)*(k in b):B.add(k)
open('out.txt','w').write(''.join('.X\n'[(k in B)-(k%81<1)]for k in R))