Alex Rivera | Logout

Code Golf: Conway's Game of Life

Asked 2010-08-17T05:22:28.323
76

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:

................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
......................
Edit
Report

5 Answers

40

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.

answered 2010-08-18T14:37:00.873
33

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

answered 2010-08-18T17:37:34.463
10

Java, 441... 346


  • Update 1 Removed inner if and more ugliness
  • Update 2 Fixed a bug and gained a character
  • Update 3 Using lots more memory and arrays while ignoring some boundaries issues. Probably a few chars could be saved.
  • Update 4 Saved a few chars. Thanks to BalusC.
  • Update 5 A few minor changes to go below 400 and make it just that extra bit uglier.
  • Update 6 Now things are so hardcoded may as well read in the exact amount in one go. Plus a few more savings.
  • Update 7 Chain the writing to the file to save a char. Plus a few odd bits.

Just playing around with BalusC's solution. Limited reputation means I couldnt add anything as a comment to his.

class M{public static void main(String[]a)throws Exception{int t=3240,j=t,i=new Integer(a[1])*t+t;char[]b=new char[i+t],p={1,80,81,82};for(new java.io.FileReader(a[0]).read(b,t,t);j<i;){char c=b[j],l=0;for(int n:p)l+=b[j+n]/88+b[j-n]/88;b[j+++t]=c>10?(l==3|l+c==90?88:'.'):c;}new java.io.FileWriter("out.txt").append(new String(b,j,t)).close();}}

More readable(?) version:

class M{
 public static void main(String[]a)throws Exception{
  int t=3240,j=t,i=new Integer(a[1])*t+t;
  char[]b=new char[i+t],p={1,80,81,82};
  for(new java.io.FileReader(a[0]).read(b,t,t);j<i;){
    char c=b[j],l=0;
    for(int n:p)l+=b[j+n]/88+b[j-n]/88;
    b[j+++t]=c>10?(l==3|l+c==90?88:'.'):c;
  }
  new java.io.FileWriter("out.txt").append(new String(b,j,t)).close();
 }
}
answered 2010-08-18T17:07:40.453
3

PHP - 365 328 322 Characters.


list(,$n,$l) = $_SERVER["argv"];
$f = file( $n );
for($j=0;$j<$l;$j++){   
    foreach($f as $k=>$v){  
        $a[$k]="";      
        for($i=0;$i < strlen( $v );$i++ ){
            $t = 0;
            for($m=-1;$m<2;$m++){
                for($h=-1;$h<2;$h++){
                    $t+=ord($f[$k + $m][$i + $h]);
                }
            }
            $t-=ord($v[$i]);          
            $a[$k] .= ( $t == 494 || ($t == 452 && ord($v[$i])==88)) ?  "X" : "." ;
        }
    }
    $f = $a;
}       
file_put_contents("out.txt", implode("\n", $a )); 

I'm sure this can be improved upon but I was curious what it would look like in PHP. Maybe this will inspire someone who has a little more code-golf experience.

  • Updated use list() instead of $var = $_SERVER["argv"] for both args. Nice one Don
  • Updated += and -= this one made me /facepalm heh cant believe i missed it
  • Updated file output to use file_put_contents() another good catch by Don
  • Updated removed initialization of vars $q and $w they were not being used
answered 2010-08-20T17:36:15.957
2

R 340 chars

cgc<-function(i="in.txt",x=100){
    require(simecol)
    z<-file("in.txt", "rb")
    y<-matrix(data=NA,nrow=40,ncol=80)
    for(i in seq(40)){
        for(j in seq(80)){
            y[i,j]<-ifelse(readChar(z,1) == "X",1,0)
        }
        readChar(z,3)
    }
    close(z)
    init(conway) <- y
    times(conway)<-1:x
    o<-as.data.frame(out(sim(conway))[[100]])
    write.table(o, "out.txt", sep="", row.names=FALSE, col.names=FALSE)
}
cgc()

I feel it's slightly cheating to have an add in package that does the actual automata for you, but I'm going with it cos I still had to thrash around with matricies and stuff to read in the file with 'X' instead of 1.

This is my first 'code golf', interesting....

answered 2010-08-20T12:54:49.730

Your Answer