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:

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

Johan
  • 74,508
  • 24
  • 191
  • 319
hb2pencil
  • 892
  • 1
  • 8
  • 13
  • 22
    This is such a great code golf! And I totally believe it belongs to SO. I found a great implementation in APL a few days ago: http://www.youtube.com/watch?v=a9xAKttWgP4 – Victor Hurdugaci Aug 17 '10 at 06:01
  • Acceptable idea but you need to tighten it up. http://meta.stackexchange.com/questions/24242/acceptable-level-of-code-golf-questions – zaf Aug 17 '10 at 06:26
  • 4
    relative popularity is a bad metric for golf. perl always gets a lot of votes even when it's not the shortest and even it if doesn't meet the spec. you should stick to the character count. People with more verbose languages still get to compete amongst themselves – John La Rooy Aug 17 '10 at 09:26
  • 2
    Are there newlines in the input file? – Gabe Aug 18 '10 at 17:22
  • ^ And are they required in the output file? – Mladen Jablanović Aug 18 '10 at 20:17
  • Newlines are required in both. I should have clarified that earlier. – hb2pencil Aug 18 '10 at 21:16
  • "You don't need to deal with the edges of the board (wraparound, infinite grids .etc)" — Does this mean that we may use wrap-around or infinite grids to avoid special code for the edges, or that we don't have to put in special code to provide wrap-around or infinite grids? – P Daddy Aug 18 '10 at 22:39
  • It means that you can do whatever you want with the edge-cases. Things can disappear, break .etc Whatever is the most succinct. As long as things not in the edges of the board work properly. – hb2pencil Aug 18 '10 at 23:02
  • Does mmap() count as "file I/O to read/write the files" ? – mvds Aug 20 '10 at 12:14
  • @tenfour Here is the Excel one: http://blogs.msdn.com/b/excel/archive/2007/11/02/iteration-conway-s-game-of-life.aspx – Dr. belisarius Aug 20 '10 at 13:02
  • @mvds As long as the data is somehow taken from the specified input file and the result written to the output file, it is fine. For instance, you should be able to open the input and result files in a text editor. – hb2pencil Aug 20 '10 at 18:30

24 Answers24

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.

Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
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 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!
Community
  • 1
  • 1
gnovice
  • 125,304
  • 15
  • 256
  • 359
30

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ć
  • 43,461
  • 10
  • 90
  • 113
  • 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 Aug 19 '10 at 00:09
  • I don't think you can compare `v` (a string) with an integer. – Mladen Jablanović Aug 19 '10 at 12:54
  • so try `v.?v:l==3||v.ord-l==84??X:?.}}` to save 7. – AShelly Aug 19 '10 at 13:48
  • nice, but doesn't this overwrite newlines when the live cells get near the edge? – AShelly Aug 19 '10 at 17:04
  • 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ć Aug 19 '10 at 17:31
  • 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 Aug 19 '10 at 18:10
24

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
  • 332
  • 2
  • 13
20

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))
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • 1
    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 Aug 30 '10 at 07:04
20

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.

Community
  • 1
  • 1
P Daddy
  • 28,912
  • 9
  • 68
  • 92
  • `open(f).readlines()` should be put as `list(open(f))`. Equivalent and six characters shorter minified and 3 bytes shorter zipped and curiously 4 characters shorter zipped with EOL at EOF, which makes it 206 (zipped with EOL) and 228 (minified without EOL). – Chris Morgan Aug 13 '11 at 08:46
14

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
  • 5,406
  • 1
  • 26
  • 31
10

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
  • 117,631
  • 17
  • 236
  • 300
10

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
  • 34,686
  • 15
  • 91
  • 152
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();
 }
}
Molehill
  • 35
  • 6
9

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
  • 54,104
  • 13
  • 100
  • 195
7

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
  • 33,034
  • 36
  • 130
  • 210
  • 4
    @Platinum Azure: You mean someone else had this idea before? Honestly, I did not see it in another thread. – Adrian Grigore Aug 19 '10 at 13:32
  • have a look at this answer: http://stackoverflow.com/questions/284797/hello-world-in-less-than-20-bytes/284898#284898 – devio Aug 19 '10 at 13:56
  • 3
    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 Aug 19 '10 at 14:04
  • 2
    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 Aug 19 '10 at 16:33
  • 1
    @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 Aug 19 '10 at 19:19
  • @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 Aug 19 '10 at 21:49
  • 1
    @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 Aug 19 '10 at 22:17
  • 1
    Hm. Include the interpreter for your language in your character count. ;) – hb2pencil Aug 20 '10 at 01:04
  • 2
    Hey, that's just my interpreter. Did the Javascript solutions include the character count for the javascript engine? ;-) – Adrian Grigore Aug 20 '10 at 07:48
  • 2
    @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. – Tom Pažourek Aug 20 '10 at 13:12
  • I think it's very creative. I'd love to see it working ... please post the compiler code when ready :D – Dr. belisarius Aug 20 '10 at 23:48
  • 4
    I thought this was a joke until I read all the serious comments. – kirk.burleson Aug 22 '10 at 13:00
5

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
  • 46,796
  • 4
  • 39
  • 32
5

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
  • 35
  • 6
5

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
  • 920
  • 1
  • 6
  • 13
4

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!

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 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. – Puppy Aug 18 '10 at 21:20
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
Nathan
  • 1,445
  • 2
  • 11
  • 29
2

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';}}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
Inverse
  • 4,408
  • 2
  • 26
  • 35
  • 1
    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 Aug 20 '10 at 15:07
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....

PaulHurleyuk
  • 8,009
  • 15
  • 54
  • 78
1

RUST - 469 characters Don't know if I should post this here, (this post is 3 years old) but anyway, my try on this, in rust (0.9):

use std::io::fs::File;fn main(){
let mut c=File::open(&Path::new(std::os::args()[1])).read_to_end();
for _ in range(0,from_str::<int>(std::os::args()[2]).unwrap()){
let mut b=c.clone();for y in range(0,40){for x in range(0,80){let mut s=0;
for z in range(x-1,x+2){for t in range(y-1,y+2){
if z>=0&&t>=0&&z<80&&t<40&&(x !=z||y !=t)&&c[t*81+z]==88u8{s +=1;}}}
b[y*81+x]=if s==3||(s==2&&c[y*81+x]==88u8){88u8} else {46u8};}}c = b;}
File::create(&Path::new("out.txt")).write(c);}

For people interested, here is the code before some agressive golfing:

use std::io::fs::File;
fn main() {
    let f = std::os::args()[1];
    let mut c = File::open(&Path::new(f)).read_to_end();    
    let n = from_str::<int>(std::os::args()[2]).unwrap();   
    for _ in range(0,n)
    {
        let mut new = c.clone();
        for y in range(0,40) {
            for x in range(0,80) {
                let mut sum = 0;
                for xx in range(x-1,x+2){
                    for yy in range(y-1,y+2) {
                        if xx >= 0 && yy >= 0 && xx <80 && yy <40 && (x != xx || y != yy) && c[yy*81+xx] == 88u8
                        { sum = sum + 1; }
                    }
                }
                new[y*81+x] = if sum == 3 || (sum == 2 && c[y*81+x] == 88u8) {88u8} else {46u8};                    
            }
        }
        c = new;
    }
    File::create(&Path::new("out.txt")).write(c);
}
OlivierH
  • 385
  • 3
  • 12
1

ét voilà you may want to use this html file. no file input, but a textarea that does the job! there is also some html and initiation and vars. the main routine has only 235 characters. It's hand-minified JS.

<!DOCTYPE html>
<html><body><textarea id="t" style="width:600px;height:600px;font-family:Courier">
</textarea></body><script type="text/javascript">var o,c,m=new Array(3200),
k=new Array(3200),y,v,l,p;o=document.getElementById("t");for(y=0;y<3200;y++)
{m[y]=Math.random()<0.5;}setInterval(function(){p="";for(y=0;y<3200;y++){c=0;
for(v=-1;v<2;v+=2){c+=m[y-1*v]?1:0;for(l=79;l<82;l++)c+=m[y-l*v]?1:0;}
k[y]=c==3||m[y]&&c==2;}p="";for(y=0;y<3200;y++){p+=(y>0&&y%80==0)?"\n":"";
m[y]=k[y];p+=(m[y]?"O":"-");}o.innerHTML=p;},100);</script></html>
redestructa
  • 1,182
  • 1
  • 11
  • 11
1

Perl – 214 chars

What, no perl entries yet?

$i=pop;@c=<>;@c=map{$r=$_;$u='';for(0..79)
{$K=$_-1;$R=$r-1;$u.=((&N.(&N^"\0\W\0").&N)=~y/X//
|(substr$c[$r],$_,1)eq'X')==3?'X':'.';}$u}keys@c for(1..$i);
sub N{substr$c[$R++],$K,3}open P,'>','out.txt';$,=$/;print P@c

Run with:

conway.pl infile #times
Bogdev
  • 306
  • 2
  • 3
1

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
  • 63
  • 4
0

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
  • 11,334
  • 2
  • 25
  • 33
  • 10
    I think perhaps you have misunderstood the point of code golf questions. – gnovice Aug 19 '10 at 23:20
  • Here is a collection of patterns in case you get hooked like I did several years ago http://www.argentum.freeserve.co.uk/lex.htm – dbasnett Aug 19 '10 at 23:22
  • @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 Aug 19 '10 at 23:24
  • 1
    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 Aug 20 '10 at 00:13
  • 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 Aug 20 '10 at 00:24