代码高尔夫: 康威的生活游戏

挑战: 编写实现约翰 · H · 康威的 生命的游戏细胞自动机的最短程序

编辑: 经过大约一周的竞争,我选择了一个胜利者: Pdehaan,用 perl 设法用 字符击败 Matlab 解决方案。

对于那些没有听说过游戏的生活,你采取一个网格(理想的无限)的方格。细胞可以是活的(填充的) ,也可以是死的(空的)。我们通过应用以下规则来确定下一步哪些细胞是活的:

  1. 任何有少于两个活细胞的活细胞都会死亡,好像是由于人口不足引起的。
  2. 任何有三个以上活细胞邻居的活细胞都会死亡,就好像过度拥挤一样。
  3. 任何有两到三个活细胞邻居的活细胞都能延续到下一代。
  4. 任何有三个活细胞邻居的死细胞都会变成活细胞,就像繁殖一样。

您的程序将读入一个40x80字符的 ASCII 文本文件,该文件指定为命令行参数,以及要执行的迭代次数(N)。最后,它将在 N 次迭代后将系统的状态输出到一个 ASCII 文件 out.txt。

下面是一个运行相关文件的示例:

返回文章页面

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

重复100次:

Q:\>life in.txt 100

结果输出(out.txt)

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

规则:

  • 您需要使用文件 I/O 来读/写文件。
  • 您需要接受输入文件和迭代次数作为参数
  • 您需要以指定的格式生成 out.txt (如果存在则覆盖)
  • 你的 不要需要处理板的边缘(包围,无限网格等)
  • 编辑: 需要在输出文件中使用换行符。

优胜者将由角色数量决定。

祝你好运!

19277 次浏览

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

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

[编辑]是的,它是:

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

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.

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 :)

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)

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.

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.

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!

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();
}
}

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!

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

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.

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.

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

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

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';}}

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);
}

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

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

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

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

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.

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

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);
}

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