views:

3072

answers:

22

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!

+18  A: 

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))
gnibbler
it breaks my heart to see python obfuscated is such a way ;Pnice job :)
townsean
Obfuscated? I thought that was pretty clean? `;)`
Kyle Rozendo
Python 2.7 no longer accepts `range(3e3)` :(
KennyTM
But 2.7 (and 3.x) accepts braces for set comprehension so `set(...)` can be replaced with `{...}`, and replacing `range(3e3)` with `range(3000)` gives a net improvement of 2 characters.
Don O'Donnell
+6  A: 

Scala - 467 364 339 chars

object G{def main(a:Array[String]){val l=io.Source.fromFile(new java.io.File(a(0)))getLines("\n")map(_.toSeq)toSeq
val f=new java.io.FileWriter("out.txt")
f.write((1 to a(1).toInt).foldLeft(l){(t,_)=>(for(y<-0 to 39)yield(for(x<-0 to 79)yield{if(x%79==0|y%39==0)'.'else{val m=t(y-1)
val p=t(y+1);val s=Seq(m(x-1),m(x),m(x+1),t(y)(x-1),t(y)(x+1),p(x-1),p(x),p(x+1)).count('X'==_)
if(s==3|(s==2&t(y)(x)=='X'))'X'else'.'}})toSeq)toSeq}map(_.mkString)mkString("\n"))
f.close}}

I think there is much room for improvement...

[Edit] Yes, it is:

object G{def main(a:Array[String]){var l=io.Source.fromFile(new java.io.File(a(0))).mkString
val f=new java.io.FileWriter("out.txt")
var i=a(1).toInt
while(i>0){l=l.zipWithIndex.map{case(c,n)=>if(c=='\n')'\n'else{val s=Seq(-83,-82,-81,-1,1,81,82,83).map(_+n).filter(k=>k>=0&k<l.size).count(l(_)=='X')
if(s==3|(s==2&c=='X'))'X'else'.'}}.mkString
i-=1}
f.write(l)
f.close}}

[Edit] And I have the feeling there is still more to squeeze out...

object G{def main(a:Array[String]){val f=new java.io.FileWriter("out.txt")
f.write(((1 to a(1).toInt):\(io.Source.fromFile(new java.io.File(a(0))).mkString)){(_,m)=>m.zipWithIndex.map{case(c,n)=>
val s=Seq(-83,-82,-81,-1,1,81,82,83)count(k=>k+n>=0&k+n<m.size&&m(k+n)=='X')
if(c=='\n')c else if(s==3|s==2&c=='X')'X'else'.'}.mkString})
f.close}}
Landei
You made me read the Scala Wikipedia article. What a beautiful language! :)
Vincent
Yes, it is. It changed my life.
Landei
+26  A: 

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.

Mladen Jablanović
Just wait until Perl guys come... ;)
Mladen Jablanović
@hb2pencil, Mladen, I don't think a code-golf answer has ever been accepted before at least one perl entry has been submitted :)
gnibbler
I see that the competition is heating up, so I will wait. Thanks!
hb2pencil
I think you can subtract 12 chars by replacing the 3rd line with `v<13?v:l==3||v-l==?T?X:?.}}`. But I don't have 1.9 installed to test it.
AShelly
I don't think you can compare `v` (a string) with an integer.
Mladen Jablanović
so try `v<?.?v:l==3||v.ord-l==84??X:?.}}` to save 7.
AShelly
Thanks, that works, but I think it won't be needed anymore. ;)
Mladen Jablanović
nice, but doesn't this overwrite newlines when the live cells get near the edge?
AShelly
True, I'm not sure if that's ok with the rule: "It means that you can do whatever you want with the edge-cases. Things can disappear, break .etc". Will roll back if @hb2pencil says not ok.
Mladen Jablanović
That sounds fine to me. It's better to just assume edge-cases will break entries anyway, as everyone would handle edge-cases differently, were they required.
hb2pencil
@AShelly: BTW, great suggestion there, now that I analyzed it! Both for handling newlines and for that trick with 84.
Mladen Jablanović
+9  A: 

F#, 496

I could reduce this a lot, but I like this as it's still in the ballpark and pretty readable.

open System.IO
let mutable a:_[,]=null
let N y x=
 [-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1]
 |>Seq.sumBy(fun(i,j)->try if a.[y+i,x+j]='X' then 1 else 0 with _->0)
[<EntryPoint>]
let M(r)=
 let b=File.ReadAllLines(r.[0])
 a<-Array2D.init 40 80(fun y x->b.[y].[x])
 for i=1 to int r.[1] do 
  a<-Array2D.init 40 80(fun y x->
   match N y x with|3->'X'|2 when a.[y,x]='X'->'X'|_->'.')
 File.WriteAllLines("out.txt",Array.init 40(fun y->
  System.String(Array.init 80(fun x->a.[y,x]))))
 0

EDIT

428

By request, here's my next stab:

open System
let mutable a,k=null,Array2D.init 40 80
[<EntryPoint>]
let M r=
 a<-k(fun y x->IO.File.ReadAllLines(r.[0]).[y].[x])
 for i=1 to int r.[1] do a<-k(fun y x->match Seq.sumBy(fun(i,j)->try if a.[y+i,x+j]='X'then 1 else 0 with _->0)[-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1]with|3->'X'|2 when a.[y,x]='X'->'X'|_->'.')
 IO.File.WriteAllLines("out.txt",Array.init 40(fun y->String(Array.init 80(fun x->a.[y,x]))))
 0

That's a 14% reduction with some basic golfing. I can't help but feel that I'm losing by using a 2D-array/array-of-strings rather than a 1D array, but don't feel like doing that transform now. Note how I elegantly read the file 3200 times to initialize my array :)

Brian
Please reduce it a lot, I'm curious!
Landei
Sigh, I guess I have to put my money where my mouth is...
Brian
"read the file 3200 times"... gotta love code golf. +1
sdolan
...elegantly. :D :D :D
Gleno
+6  A: 

Javascript/Node.js - 233 236 characters

a=process.argv
f=require('fs')
m=46
t=f.readFileSync(a[2])
while(a[3]--)t=[].map.call(t,function(c,i){for(n=g=0;e=[-82,-81,-80,-1,1,80,81,82][g++];)t[i+e]>m&&n++
return c<m?c:c==m&&n==3||c>m&&n>1&&n<4?88:m})
f.writeFile('out.txt',t)
MooGoo
+25  A: 
belisarius
Based on the animation, that doesn't appear to be evolving correctly.
gnovice
having a built-in `CellularAutomaton` function seems to take some of the challenge out.
AShelly
@gnovice yep. there was a bug ... tnx!
belisarius
@AShelly I guess code-golf challenges can be undertaken both ways > Tweak a non-well-fitted tool or Find a Good Tool
belisarius
Aw, using CellularAutomaton seems like cheating...
Adrian Grigore
@Adrian Different challenges in different languages. In Mathematica the ASCII formatting is a headache ...
belisarius
+10  A: 

Ruby 1.8: 178 175 chars

f,n=$*;b=IO.read f
n.to_i.times{s=b.dup
s.size.times{|i|t=([82,1,-80].map{|o|b[i-o,3]||''}*'').count 'X'
s[i]=t==3||b[i]-t==?T??X:?.if s[i]>13};b=s}
File.new('out.txt','w')<<b

Newlines are significant (although all can be replaced w/ semicolons.)

Edit: fixed the newline issue, and trimmed 3 chars.

AShelly
Lines in the output file doesn't seem separated.
Mladen Jablanović
they're not - but they display perfectly in my 80 char console.
AShelly
You need to have newlines; sorry for not pointing that out explicitly.
hb2pencil
+4  A: 

Java, 556 532 517 496 472 433 428 420 418 381 chars


  • Update 1: replaced 1st StringBuffer by Appendable and 2nd by char[]. Saved 24 chars.

  • Update 2: found a shorter way to read file into char[]. Saved 15 chars.

  • Update 3: replaced one if/else by ?: and merged char[] and int declarations. Saved 21 chars.

  • Update 4: replaced (int)f.length() and c.length by s. Saved 24 chars.

  • Update 5: made improvements as per hints of Molehill. Major one was hardcoding the char length so that I could get rid of File. Saved 39 chars.

  • Update 6: minor refactoring. Saved 6 chars.

  • Update 7: replaced Integer#valueOf() by new Integer() and refactored for loop. Saved 8 chars.

  • Update 8: Improved neighbour calculation. Saved 2 chars.

  • Update 9: Optimized file reading since file length is already hardcoded. Saved 37 chars.


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

More readable version:

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

Closing after writing is absoletely mandatory, else the file is left empty. It would otherwise have saved another 21 chars.

Further I could also save one more char when I use 46 instead of '.', but both javac and Eclipse jerks with a compilation error Possible loss of precision. Weird stuff.


Note: this expects an input file with \n newlines, not \r\n as Windows by default uses!

BalusC
You could just use new FileWriter(out.txt).write(c) to say a few characters. Unfortunately you can't chuck the whole variable as write() doesn't return this. If you could find a file writing class that does, substantial savings could be made. Also, I like your use of throws-everything to avoid those horrendous enforced catches.
DeadMG
@DeadMG: Closing is mandatory, else buffer won't be flushed.
BalusC
+9  A: 

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();
 }
}
Molehill
String instead of char[] is more expensive but this truly doesn't matter in code golf! Nice one :)
BalusC
Note that the total file/char length is not 2754 chars.
BalusC
@BallusC Thanks, I managed to only copy 34 rows rather than all 40!
Molehill
That's indeed a real memory hog! Btw `--i` can go in `new char[i--*t]` and `b[l++]+=(char)j` can just be `b[l++]=(char)j`. That saves another 3 chars.
BalusC
Btw: why did you remove the ``, saves 4 chars.
BalusC
It shouldn't have (had) any out of bounds as it will just read into the next iteration's part of the buffer. Thanks for the extra tips.
Molehill
+23  A: 

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!
gnovice
how many extra chars to launch it from the command line?
AShelly
@AShelly: After digging a bit more, I discovered that it is possible to call MATLAB functions with a command syntax (which I hadn't thought was possible before). I added this other solution to my answer. It only adds 6 characters.
gnovice
+10  A: 

Haskell - 284 272 232 chars

import System
main=do f:n:_<-getArgs;s<-readFile f;writeFile"out.txt"$t s$read n
p '\n'_='\n'
p 'X'2='X'
p _ 3='X'
p _ _='.'
t r 0=r
t r n=t[p(r!!m)$sum[1|d<-1:[80..82],s<-[1,-1],-m<=d*s,m+d*s<3240,'X'==r!!(m+d*s)]|m<-[0..3239]]$n-1
Alexander Konstantinov
A: 

The following solution uses my own custom domain-specific programming language which I have called NULL:

3499538

In case you are wondering how this works: My language consists of only of one statment per program. The statement represents a StackOverflow thread ID belonging to a code golf thread. My compiler compiles this into a program that looks for the best javascript solution (with the SO API), downloads it and runs it in a web browser.

Runtime could be better for new threads (it may take some time for the first upvoted Javascript answer to appear), but on the upside it requires only very little coding skills.

Adrian Grigore
This is not funny any more. Seriously. It's just stupid now.
Platinum Azure
@Platinum Azure: You mean someone else had this idea before? Honestly, I did not see it in another thread.
Adrian Grigore
have a look at this answer: http://stackoverflow.com/questions/284797/hello-world-in-less-than-20-bytes/284898#284898
devio
Well, I guess great minds think alike ;-). But in contrast to the solution above, my solution can actually solve virtually all code golf challenges, whereas the one above can only print "Hello World".
Adrian Grigore
It is not Turing complete, it cannot interpret abstract code. It does not necessarily work every time as there may never be a valid (javascript) solution. It should not be on Code Golf.
Callum Rogers
@Callum Rogers: The link above shows an answer with 245 upvotes which is IMO inferior. Shouldn't that be on code golf either?
Adrian Grigore
@Adrian: Yes, you're right, in terms of functionality it is better. `HelloWorld` should not strictly be used. But it was the first time it was done and was funny 2 years ago. And it was written by __Jon Skeet__.
Callum Rogers
@Callum Rogers: I understand, but as as I said, I did not copycat that answer. I just had this idea today. I'll leave this up as my personal souvenir of having a better answer than Jon, even though it was a little too late. :)
Adrian Grigore
Hm. Include the interpreter for your language in your character count. ;)
hb2pencil
Hey, that's just my interpreter. Did the Javascript solutions include the character count for the javascript engine? ;-)
Adrian Grigore
@Adrian Your solution can't be tested since you haven't posted any interpreter of your language, if it can't be tested, it's useless.
tomp
I lolled :-) haters gonna hate. Keep truckin
Tom Gullen
I think it's very creative. I'd love to see it working ... please post the compiler code when ready :D
belisarius
I thought this was a joke until I read all the serious comments.
kirk.burleson
+11  A: 

Python 2.x - 210/234 characters

Okay, the 210-character code is kind of cheating.

#coding:l1
exec'xÚ=ŽA\nÂ@E÷sŠº1­ƒÆscS‰ØL™Æª··­âî¿GÈÿÜ´1iÖ½;Sçu.~H®J×Þ-‰­Ñ%ª.wê,šÖ§J®d꘲>cÉZË¢V䀻Eîa¿,vKAËÀå̃<»Gce‚ÿ‡ábUt¹)G%£êŠ…óbÒüíÚ¯GÔ/n×Xši&ć:})äðtÏÄJÎòDˆÐÿG¶'.decode('zip')

You probably won't be able to copy and paste this code and get it to work. It's supposed to be Latin-1 (ISO-8859-1), but I think it got perverted into Windows-1252 somewhere along the way. Additionally, your browser may swallow some of the non-ASCII characters.

So if it doesn't work, you can generate the file from plain-old 7-bit characters:

s = """
23 63 6F 64 69 6E 67 3A 6C 31 0A 65 78 65 63 27 78 DA 3D 8E 41 5C 6E C2
40 0C 45 F7 73 8A BA 31 13 AD 83 15 11 11 C6 73 08 63 17 05 53 89 D8 4C
99 C6 AA B7 B7 AD E2 EE BF 47 C8 FF DC B4 31 69 D6 BD 3B 53 E7 75 2E 7E
48 AE 4A D7 DE 90 8F 2D 89 AD D1 25 AA 2E 77 16 EA 2C 9A D6 A7 4A AE 64
EA 98 B2 3E 63 C9 5A CB A2 56 10 0F E4 03 80 BB 45 16 0B EE 04 61 BF 2C
76 0B 4B 41 CB C0 E5 CC 83 03 3C 1E BB 47 63 65 82 FF 87 E1 62 55 1C 74
B9 29 47 25 A3 EA 03 0F 8A 07 85 F3 62 D2 FC ED DA AF 11 47 D4 2F 6E D7
58 9A 69 26 C4 87 3A 7D 29 E4 F0 04 74 CF C4 4A 16 CE F2 1B 44 88 1F D0
FF 47 B6 27 2E 64 65 63 6F 64 65 28 27 7A 69 70 27 29
"""

with open('life.py', 'wb') as f:
    f.write(''.join(chr(int(i, 16)) for i in s.split()))

The result of this is a valid 210-character Python source file. All I've done here is used zip compression on the original Python source code. The real cheat is that I'm using non-ASCII characters in the resultant string. It's still valid code, it's just cumbersome.

The noncompressed version weighs in at 234 characters, which is still respectable, I think.

import sys
f,f,n=sys.argv
e=open(f).readlines()
p=range
for v in p(int(n)):e=[''.join('.X'[8+16*(e[t][i]!='.')>>sum(n!='.'for v in e[t-1:t+2]for n in v[i-1:i+2])&1]for i in p(80))for t in p(40)]
open('out.txt','w').write('\n'.join(e))

Sorry about the horizontal scroll, but all newlines in the above are required, and I've counted them as one character each.

I wouldn't try to read the golfed code. The variable names are chosen randomly to achieve the best compression. Yes, I'm serious. A better-formatted and commented version follows:

# get command-line arguments: infile and count
import sys
ignored, infile, count = sys.argv

# read the input into a list (each input line is a string in the list)
data = open(infile).readlines()

# loop the number of times requested on the command line
for loop in range(int(count)):
    # this monstrosity applies the rules for each iteration, replacing
    # the cell data with the next generation
    data = [''.join(

                # choose the next generation's cell from '.' for
                # dead, or 'X' for alive
                '.X'[

                    # here, we build a simple bitmask that implements
                    # the generational rules.  A bit from this integer
                    # will be chosen by the count of live cells in
                    # the 3x3 grid surrounding the current cell.
                    #
                    # if the current cell is dead, this bitmask will
                    # be 8 (0b0000001000).  Since only bit 3 is set,
                    # the next-generation cell will only be alive if
                    # there are exactly 3 living neighbors in this
                    # generation.
                    #
                    # if the current cell is alive, the bitmask will
                    # be 24 (8 + 16, 0b0000011000).  Since both bits
                    # 3 and 4 are set, this cell will survive if there
                    # are either 3 or 4 living cells in its neighborhood,
                    # including itself
                    8 + 16 * (data[y][x] != '.')

                    # shift the relevant bit into position
                    >>

                    # by the count of living cells in the 3x3 grid
                    sum(character != '.' # booleans will convert to 0 or 1
                        for row in data[y - 1 : y + 2]
                        for character in row[x - 1 : x + 2]
                    )

                    # select the relevant bit
                    & 1
                ]

               # for each column and row
                for x in range(80)
            )
            for y in range(40)
    ]

# write the results out
open('out.txt','w').write('\n'.join(data))

Sorry, Pythonistas, for the C-ish bracket formatting, but I was trying to make it clear what each bracket was closing.

P Daddy
+1 Well done, unicode is fair game for codegolf on SO - not "kind of cheating" at all
gnibbler
A: 

One of the classic patterns

***
..*
.*

My avatar was created using my version of the Game of Life using this pattern and rule(note that it is not 23/3):

#D Thanks to my daughter Natalie
#D Try at cell size of 1
#R 8/1
#P -29 -29
.*********************************************************
*.*******************************************************.*
**.*****************************************************.**
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
****************************.*.****************************
***********************************************************
****************************.*.****************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
***********************************************************
**.*****************************************************.**
*.*******************************************************.*
.*********************************************************

IMHO - as I learned Conway's Game of Life the trick wasn't writing short code, but code that could do complex life forms quickly. Using the classic pattern above and a wrapped world of 594,441 cells the best I could ever do was around 1,000 generations / sec.

Another simple pattern

**********
.
................*
.................**
................**.......**********

And gliders

........................*...........
......................*.*...........
............**......**............**
...........*...*....**............**
**........*.....*...**..............
**........*...*.**....*.*...........
..........*.....*.......*...........
...........*...*....................
............**......................
dbasnett
I think perhaps you have misunderstood the point of code golf questions.
gnovice
Here is a collection of patterns in case you get hooked like I did several years agohttp://www.argentum.freeserve.co.uk/lex.htm
dbasnett
@gnovice - no, but it was a topic I had a lot of fun with. The cellular automata might be a fun shortest code question, but it is also a fun topic all by itself. I'll butt out now.
dbasnett
If you are experienced in a language not represented here, I encourage you to submit a code-golf entry -- all are appreciated, even if it lags a bit behind the others in terms of length. :)
hb2pencil
Just the Automaton code is almost 2000 lines. The drawing / editing (graphically) / pattern file handling maybe 2000 more. So I guess I would be over par for my round ;)
dbasnett
A: 

c++ - 492 454 386


my first code golf ;)

#include<fstream>
#define B(i,j)(b[i][j]=='X')
int main(int i,char**v){for(int n=0;n<atoi(v[2]);++n){std::ifstream f(v[1]);v[1]="out.txt";char b[40][83];for(i=0;i<40;++i)f.getline(b[i],83);std::ofstream g("out.txt");g<<b[0]<<'\n';for(i=1;i<39;++i){g<<'.';for(int j=1;j<79;++j){int k=B(i-1,j)+B(i+1,j)+B(i,j-1)+B(i,j+1)+B(i-1,j-1)+B(i+1,j+1)+B(i+1,j-1)+B(i-1,j+1);(B(i,j)&&(k<2||k>3))?g<<'.':(!B(i,j)&&k==3)?g<<'X':g<<b[i][j];}g<<".\n";}g<<b[0]<<'\n';}}

A somewhat revised version, replacing some of the logic with a table lookup+a few other minor tricks:

#include<fstream>
#define B(x,y)(b[i+x][j+y]=='X')
int main(int i,char**v){for(int n=0;n<atoi(v[2]);++n){std::ifstream f(v[1]);*v="out.txt";char b[40][83], O[]="...X.....";for(i=0;i<40;++i)f>>b[i];std::ofstream g(*v);g<<b[0]<<'\n';for(i=1;i<39;++i){g<<'.';for(int j=1;j<79;++j){O[2]=b[i][j];g<<O[B(-1,0)+B(1,0)+B(0,-1)+B(0,1)+B(-1,-1)+B(1,1)+B(1,-1)+B(-1,1)];}g<<".\n";}g<<b[0]<<'\n';}}
Inverse
Some tips: you don't need to call the arguments to main argc and argv. Try c and v instead. Also try using the ternary operator instead of if/else. Good to see C++ represented. :)
hb2pencil
+2  A: 

C - 300


Just wondered how much smaller and uglier my java solution could go in C. Reduces to 300 including the newlines for the preprocessor bits. Leaves freeing the memory to the OS! Could save ~20 by assuming the OS will close and flush the file too.

#include<stdio.h>
#include<stdlib.h>
#define A(N)j[-N]/88+j[N]/88

int main(int l,char**a){
  int t=3240,i=atoi(a[2])*t+t;
  char*b=malloc(i+t),*j;
  FILE*f;
  fread(j=b+t,1,t,fopen(a[1],"r"));
  for(;j-b-i;j++[t]=*j>10?l==3|l+*j==90?88:46:10)
      l=A(1)+A(80)+A(81)+A(82);
  fwrite(j,1,t,f=fopen("out.txt","w"));
  fclose(f);
}
Molehill
+1  A: 

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....

PaulHurleyuk
+3  A: 

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
Nathan
list($n,$l) = $_SERVER['argv'];
Don Wilson
CHANGE: $o= fopen ("out.txt", "w");fwrite($o, implode("\n", $a ) );fclose ($o); TO: file_put_contents("out.txt", implode("\n",$a));
Don Wilson
CHANGE: $t=$t-ord($v[$i]); TO: $t-=ord($v[$i]);
Don Wilson
CHANGE: $t=$t+ord($f[$k + $m][$i + $h]); TO $t+=ord($f[$k + $m][$i + $h]);
Don Wilson
+1  A: 
Bogdev
+8  A: 

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
pdehaan
Very nice! You managed to beat a couple specialized languages with a more general-purpose one. :)
hb2pencil
does this write to 'out.txt'?
AShelly
`@b=<>=~/./g` saves 3 more char
mobrule
A: 

Another Java attempt, 361 chars

class L{public static void main(final String[]a)throws Exception{new java.io.RandomAccessFile("out.txt","rw"){{int e=88,p[]={-1,1,-80,80,-81,81,-82,82},s=3240,l=0,i=new Byte(a[1])*s+s,c;char[]b=new char[s];for(new java.io.FileReader(a[0]).read(b);i>0;seek(l=++l%s),i--){c=b[l];for(int n:p)c+=l+n>=0&l+n<s?b[l+n]/e:0;write(c>13?(c==49|(c|1)==91?e:46):10);}}};}}

And a little more readable

class L {
    public static void main(final String[]a) throws Exception {
        new java.io.RandomAccessFile("out.txt","rw"){{
            int e=88, p[]={-1,1,-80,80,-81,81,-82,82},s=3240,l=0,i=new Byte(a[1])*s+s,c;
            char[] b = new char[s];
            for (new java.io.FileReader(a[0]).read(b);i>0;seek(l=++l%s),i--) {
                c=b[l];
                for (int n:p)
                    c+=l+n>=0&l+n<s?b[l+n]/e:0;
                write(c>13?(c==49|(c|1)==91?e:46):10);
            }
        }};
    }
}

Very similar to Molehill’s version. I've tried to use a different FileWriter and to count the cell's neighbors without an additional variable. Unfortunately, RandomAccessFile is a pretty long name and it is required that you pass an file access mode.

Robert
+1  A: 

MUMPS: 314 chars

L(F,N,R=40,C=80)
    N (F,N,R,C)
    O F:"RS" U F D  C F
    .F I=1:1:R R L F J=1:1:C S G(0,I,J)=($E(L,J)="X")
    F A=0:1:N-1 F I=1:1:R F J=1:1:C D  S G(A+1,I,J)=$S(X=2:G(A,I,J),X=3:1,1:0)
    .S X=0 F i=-1:1:1 F j=-1:1:1 I i!j S X=X+$G(G(A,I+i,J+j))
    S F="OUT.TXT" O F:"WNS" U F D  C F
    .F I=1:1:R F J=1:1:C W $S(G(N,I,J):"X",1:".") W:J=C !
    Q
Clayton
That is a terrifying language. Nice character count.
hb2pencil