Reputation: 892
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:
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:
The winner will be determined by character count.
Good luck!
Upvotes: 76
Views: 20220
Reputation: 1202
é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>
Upvotes: 1
Reputation: 347
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);
}
Upvotes: 1
Reputation: 29537
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.
Upvotes: 20
Reputation: 4476
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';}}
Upvotes: 2
Reputation: 125874
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
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:
b
from a logical (i.e. "boolean") type to a numerical one to get rid of a few conversions.~~b+0
with b/42
, and replaced 'same'
with 's'
as an argument to CONV2 (and it surprisingly still worked!).b
back to a logical matrix.b
and reworked the logic in the loop to save 1 additional character.cell2mat
with char
, saving 4 characters. Thanks Eric!Upvotes: 33
Reputation: 918
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
Upvotes: 5
Reputation: 63
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.
Upvotes: 1
Reputation: 342
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
Upvotes: 24
Reputation: 1525
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.
Upvotes: 3
Reputation: 326
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
Upvotes: 1
Reputation: 11773
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
........................*...........
......................*.*...........
............**......**............**
...........*...*....**............**
**........*.....*...**..............
**........*...*.**....*.*...........
..........*.....*.......*...........
...........*...*....................
............**......................
Upvotes: 0
Reputation: 61056
Spaces added for readability
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"] &
Invoke with
s["c:\life.txt", 100]
Animation:
You can also get a graph of the mean population over time:
A nice pattern for generating gliders from Wikipedia
AFAIK Mathematica uses a Cellular Automaton to generate random numbers using Rule 30.
Upvotes: 40
Reputation: 8169
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....
Upvotes: 2
Reputation: 35
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);
}
Upvotes: 5
Reputation: 44100
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.
Upvotes: 30
Reputation: 1109432
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!
Upvotes: 4
Reputation: 35
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();
}
}
Upvotes: 10
Reputation: 33318
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.
Upvotes: 7
Reputation: 5486
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
Upvotes: 14
Reputation: 35600
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.
Upvotes: 10
Reputation: 54584
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}}
Upvotes: 9
Reputation: 118895
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
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 :)
Upvotes: 10
Reputation: 48260
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)
Upvotes: 5
Reputation: 304413
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))
Upvotes: 20