# Shortest Game of Life

Conway's Game of Life is the classic example of cellular automation. The cells form a square grid and each has two states: alive or dead. On each turn, each cell simultaneously updates according to its state and those of its eight neighbours:

• A live cell remains alive if it has exactly two or three live neighbours
• A dead cell becomes alive if it has exactly three live neighbours

Your mission, should you choose to accept it, is to code the shortest Game of Life implementation in your favourite language.

The rules:

• The grid must be at least 20x20
• The grid must wrap around (so the grid is like the surface of a Torus)
• Your implementation must allow the user to input their own starting patterns
• GoL is a bit pointless if you can't see what is happening, so there must be visual output of the automaton running, with each turn's result being shown for long enough to be seen!
• Previously on Stack Overflow: Code Golf: Conway's Game of Life, and be sure to look at the APL implementation link in the comments. Aug 14, 2011 at 3:07
• Ah, I did not see that. But this is slightly different no (save me deleting the work putting the challenge together? Aug 14, 2011 at 3:15
• It's not a problem. Many puzzles already run on Stack Overflow have been done here too, but people will tell you that I am obsessive about linking to similar challenges. Aug 14, 2011 at 3:17
• @Griffin: You can remove all those ; before }s. Also vars can be eliminated at times (if it doesn't break your code). And for one-line fors, ifs etc, you can eliminate the { } completely: for(...) for(...) dosomething(). Aug 14, 2011 at 14:21
• @pimvdb, cheers, I haven't fully golfed it yet, haven't had the time. just wanted to show that I had a go too, rather than idly setting a challenge. Will golf it to the max soon. Aug 14, 2011 at 17:53

## Python, 589 bytes

Mouse buttons: left - put a cell, right - remove a cell, middle - start/stop.

from Tkinter import*
import copy
z=range
F=50
T=Tk()
S=9
f=[F*[0]for i in'7'*F]
c=Canvas(T,width=S*F,height=S*F)
c.pack()
def p(x,y,a):f[y][x]=f[y][x]or c.create_oval(x*S,y*S,x*S+S,y*S+S)if a else c.delete(f[y][x])
r=1
def R(e):global r;r=1-r
exec("c.bind('<Button-%i>',lambda e:p(e.x/S,e.y/S,%i));"*2%(1,1,3,0))
c.bind('<Button-2>',R)
def L():
T.after(99,L)
if r:return
g=copy.deepcopy(f)
for y in z(F):
for x in z(F):
n=8
for j in z(-1,2):
for i in z(-1,2):
if i or j:n-=not g[(y+j)%F][(x+i)%F]
if 1<n<4:
if n==3and not g[y][x]:p(x,y,1)
else:p(x,y,0)
L()
T.mainloop()

And here is a version where you can drag mouse to draw. Graphics are a bit more pleasant.

from Tkinter import*
import copy
z=range
F=50
T=Tk()
S=9
f=[F*[0]for i in'7'*F]
c=Canvas(T,bg='white',width=S*F,height=S*F)
c.pack()
def p(x,y,a):f[y][x]=f[y][x]or c.create_rectangle(x*S,y*S,x*S+S,y*S+S,fill='gray')if a else c.delete(f[y][x])
r=1
def R(e):global r;r=1-r
exec("c.bind('<Button-%i>',lambda e:p(e.x/S,e.y/S,%i));c.bind('<B%i-Motion>',lambda e:p(e.x/S,e.y/S,%i));"*2%(1,1,1,1,3,0,3,0))
c.bind('<Button-2>',R)
def L():
T.after(99,L)
if r:return
g=copy.deepcopy(f)
for y in z(F):
for x in z(F):
n=8
for j in z(-1,2):
for i in z(-1,2):
if i or j:n-=not g[(y+j)%F][(x+i)%F]
if 1<n<4:
if n==3and not g[y][x]:p(x,y,1)
else:p(x,y,0)
L()
T.mainloop()
• This doesn't follow the game of life rules correctly. Aug 23, 2011 at 13:23
• @StevenRumbalski: Oh really? Aug 23, 2011 at 14:00
• really. You have an indentation error in your second version. The section starting with if 1<n<4: should be indented at the same level as for j in z(-1,2): Aug 23, 2011 at 18:36

# Postscript 529 515

Started with the example from Rosetta Code. Invoke with a filename argument (gs -- gol.ps pulsar), the file containing 20*20 binary numbers (separated by space). Infinite loop: draw board, wait for enter, calculate next generation.

[/f ARGUMENTS 0 get(r)file/n 20>>begin[/m
n 1 sub/b[n{[n{f token pop}repeat]}repeat]/c 400
n div/F{dup 0 lt{n add}if dup n ge{n sub}if}>>begin{0
1 m{dup 0 1 m{2 copy b exch get exch get 1 xor setgray
c mul exch c mul c c rectfill dup}for pop pop}for
showpage/b[0 1 m{/x exch def[0 1 m{/y exch def 0
y 1 sub 1 y 1 add{F dup x 1 sub 1 x
1 add{F b exch get exch get 3 2 roll add exch
dup}for pop pop}for b x get y get sub b x get y get
0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq
or{1}{0}ifelse}ifelse}for]}for]def}loop

Spaced, with a few stack comments (just the ones I needed).

[
/f ARGUMENTS 0 get(r)file
/n 20
/sz 400
%/r{rand 2147483647 div}
>>begin
[
/m n 1 sub
/b[
%n{[n{r .15 le{1}{0}ifelse}repeat]}repeat
n{[n{f token pop}repeat]}repeat
]
/c sz n div
/F{dup 0 lt{n add}if dup n ge{n sub}if}
>>begin
{
0 1 m{dup % y y
0 1 m{ % y y x
2 copy b exch get exch get 1 xor setgray
c mul exch c mul c c rectfill
dup
}for pop pop}for
pstack
showpage
/b[0 1 m{/x exch def
[0 1 m{/y exch def
0
y 1 sub 1 y 1 add{F dup %s y y
x 1 sub 1 x 1 add{F %s y y x
b exch get exch get %s y bxy
3 2 roll add exch %s+bxy y
dup %s y y
}for pop pop}for
b x get y get sub
b x get y get
0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq or{1}{0}ifelse}ifelse
}for]
}for]def
}loop

pulsar data file:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

# Python 2, 456 bytes

While I know this is an old post, I couldn't help myself from giving it a shot. The initial board can be any size as long as you draw a border around it and have an extra space on the last line.

Golf.py

import time,itertools as w,sys;t,q=map(lambda x:list(x[:-1]),sys.stdin.readlines()),list(w.product(range(-1,2),range(-1,2)));del q[4];n=map(lambda x:x[:],t[:])
while time.sleep(0.1)==None:
for j in range(1,len(t)-1):
for i in range(1,len(t[j])-1):x=sum(map(lambda s:1 if t[j+s[0]][i+s[1]]in'@'else 0,q));f=t[j][i];n[j][i]='@'if(f=='@'and(x==3 or x==2))or(f==' 'and x==3)else' '
t=map(lambda x:x[:],n[:]);print'\n'.join(list(map(lambda x:''.join(x),t)))

Input.txt (note the extra space on the last line)

+----------------------------------------+
|                    @                   |
|                     @                  |
|                   @@@                  |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
+----------------------------------------+

How to Run

python Golf.py < input.txt
• time.sleep(0.1)==None => not time.sleep(.1), (f=='@'and(x==3 or x==2))or(f==' 'and x==3) => x==3or f=='@'and x==2 Jun 22, 2017 at 3:35
• ^, You forgot one, 1 if=>1if. Aug 17, 2017 at 20:05

# Processing 270,261 249 bytes

Grid is the 100*100 pixels of screen, input comes in the form of a png picture

Ungolfed

void setup() {
}
void draw() {
int c=100, i=0, n, l=c*c, b=color(0);
int[]a=new int[l], p=pixels;
for (; i<l; i++) {
n=p[(i+l-101)%l]&1;
n+=p[(i+l-100)%l]&1;
n+=p[(i+l-99)%l]&1;
n+=p[(i+l-1)%l]&1;
n+=p[(i+1)%l]&1;
n+=p[(i+99)%l]&1;
n+=p[(i+100)%l]&1;
n+=p[(i+101)%l]&1;
a[i]=n==5?b:p[i]==b&&n==6?b:-1;
}
arrayCopy(a, pixels, l);
updatePixels();
}

# JavaScript 676

Sorry Griffin, I just couldn't look at your code and not re-write it slightly... had to shave off two characters but it was damn worth it!

But as they say, it's easier to ask for forgiveness than permission... ;)

# Octave (153)

the same as Matlab by DenDenDo at Shortest Game of Life , but had to change imshow to imagesc:

b=uint8(rand(20)<0.2)
s=@(m)imfilter(m,[1 1 1;1 0 1;1 1 1],'circular')
p=@(m,n)uint8((n==3)|(m&(n==2)))
while 1
imagesc(b)
drawnow
b=p(b,s(b))
end

# Python 2: 334 Bytes

Only 6 years late.

import time
s='';s=map(list,iter(raw_input,s));k=len(s);l=(-1,0,1);n=int;z=range
while 1:
r=[[0]*k for i in z(k)]
for i in z(k*k):
a,b=i//k,i%k
m,g=sum([n(s[(a+c)%k][(b+d)%k])for c in l for d in l if c|d]),n(s[a][b])
r[a][b]=n((m==2)&g or m==3)
print'*'if r[a][b]else' ',
if b-k+1==0:print
s=r;time.sleep(.2);print"\033c"

You can run it like:

python gol.py
0000000
0001000
0000100
0011100
0000000
0000000
0000000

Where the 0s and 1s represent dead and live cells, an extra newline at the end begins execution.

Grids must be square.

It's easier to run than the shortest python one, supports any sized grids, and looks pretty when run.

It's also 100 bytes more, so there's that.

### HTML and Javascript, 248 characters

<script>b=[];setInterval(()=>x.innerHTML=(b=b.map((r,y)=>r.map((c,x)=>+(([0,1,2,4,6,8,9,10].reduce((s,n)=>s+((b[y-1+(n>>2)]||[])[x+n%4-1]||0),0)|c)==3)))).map(r=><tr>${r.map(v=><td>${'⬜⬛'[v]}).join('')}).join(''),999)</script><table id='x'>

Run it by opening the web developer console and setting the global variable b (for "board") to a 2D-array of 0 (dead) and 1 (alive) values, for example:

b=new Array(32).fill(0).map(() => new Array(32).fill(0).map(() => Math.floor(Math.random() * 2)))

The core of this is the following:

## Javascript, 114 characters

l=b=>b.map((r,y)=>r.map((c,x)=>+(([0,1,2,4,6,8,9,10].reduce((s,n)=>s+((b[y-1+(n>>2)]||[])[x+n%4-1]||0),0)|c)==3)))

Annotated as follows:

l=       // l="Life"
b=>    // Function that takes a board (2D array of ints that are 1 or 0)
b.map( // map each row
(
r, // the row (array of 1s and 0s)
y  // index is the y position of the row
)=>
r.map( //map each cell
(
c, // the cell value (0, or 1)
x  // index is the x position
)=>(+( //this whole thing will return true or false, convert to 1 or 0
// these magic numbers represent the eight neighbors of a cell
// they map to x, y offsets (used below):
// value  x     y
//      n%4-1 (n>>2)-1
[
0, //  -1    -1
1, //   0    -1
2, //   1    -1
4, //  -1     0
6, //   1     0
8, //   1    -1
9, //   1     0
10 //   1     1
]
.reduce( //get the number of neighbors that are alive (===1)
(
s, // the accumulator (sum of alive neighbors so far)
n  // the number from the list of magic numbers above
)=>
s+(  // add to the accumulator
(
b[            // find the row containing the neighbor
y-1+(n>>2)  // A shorter way of expressing y+Math.floor(n/4)-1
]||[]         // if index is -1 or b.length, empty array
)[              // within the row, find the value
x+n%4-1       // offset x value (see table above)
]||0            // coalesce undefined(x is -1 or r.length) to 0
),0               // initial value for neighborCount accumulator
)|c                 // | bitwise or with the value of the cell, 1 or zero
// if the cell is dead (0), this has no effect
// if the cell is alive (1), this changes 2 to 3
)==3)                 // 3 means either:
// 3 neighbors or
// 2 neighbors and an alive cell (the rules for life)
)
)

# QBasic, 276 271 bytes

-5 bytes thanks to Dominic van Essen

DIM a(20,20)
DO
FOR y=0TO 19
FOR x=0TO 19
IF j THEN c=a(x,y)\2ELSE c=INPUT$(1)>"0 a(x,y)=c NEXT x,y CLS FOR y=0TO 19 ? FOR x=0TO 19 ?a(x,y); n=0 FOR j=19TO 21 FOR i=19TO 21 n=n-a((x+i)MOD 20,(y+j)MOD 20)MOD 2 NEXT i,j a(x,y)=2*(n=3)+(1-2*(n=4))*a(x,y) NEXT x,y SLEEP LOOP Ways to run QBasic Disclaimer: This golfed version is extremely user-unfriendly. See below for details and a somewhat friendlier version. ### Algorithm We store the grid in the 2D array a. A value of 0 is a dead cell; a value of -1 (QBasic's default truthy value) is a living cell. The whole program is wrapped in an infinite DO ... LOOP. On the first iteration, j is 0, and so the first nested FOR loop initializes the array from user input (c=INPUT$(1)>"0). We then clear the screen with CLS and proceed to the next set of nested loops. Before each row y, we print a newline (?). Then for each cell at column x:

• We print the cell's value, suppressing the trailing newline (?a(x,y);).
• We loop over the 3x3 neighborhood around the cell. The loop indices j and i are essentially going from -1 to 1, but in QBasic, (-1) MOD num is -1 rather than num - 1, so to avoid any negative numbers we loop from 19 to 21 instead.
• For each living cell in the neighborhood, we add 1 to n.
• After the loop, we subtract 2 from the cell's value if it will be alive at the next step. A more straightforward but less golfy way to write the expression is a(x,y) = a(x,y) - 2 * ((n=3) - (n=4)*a(x,y)): subtract 2 if n=3 or if n=4 and a(x,y) is true (-1).

After the FOR loops, SLEEP pauses until the user presses a key. We then return to the top. At this point, the elements in array a can have any of four values:

• 0 is a cell that was dead last step and will remain dead.
• -1 is a cell that was alive last step but will die.
• -2 is a cell that was dead last step but will come alive.
• -3 is a cell that was alive last step and will remain alive.

When we reach the first nested FOR loop again, j is now truthy (having been used as a loop index), so we integer-divide each element by 2 (c=a(x,y)\2). Values of 0 and -1 become 0 (dead), and values of -2 and -3 become -1 (alive).

### I/O format and caveats; or: Don't Run This Code

The input format for this code is just awful. The user is expected to press a key 400 times to initialize the 400 cells. (Any key with an ASCII value of 48 ("0") or less is a dead cell; any key with a greater ASCII value is a living cell.) The worst part: none of this input is echoed to the screen. You just have to keep count in your head and hope you didn't double-press a key. In practice? Something always goes wrong.

Once all the input has been received, the raw array values are output. Because of the way QBasic formats numeric output, they do line up in a grid, like this--

0 -1  0
0  0 -1
-1 -1 -1

--but it's still not the nicest output format.

Rather than an animation per se, the code waits for a user keypress between iterations. I think this fits the spec (it shows each step long enough to be seen), and it's the golfiest way to pause in QBasic. SLEEP 1 would wait one second between each iteration for +2 bytes.

A couple more caveats:

• The code runs as an infinite loop, so you'll have to kill the program to make it exit.
• The sequence 2ELSE on line 5 is correctly parsed as 2 ELSE by actual QBasic, but the QB64 emulator has trouble with it, expecting the 2E sequence to be the start of a number in scientific notation. You'll have to add in the space if you're using QB64.

All that to say: I don't recommend you run this code as-is. Either change the array size to 5x5 (which makes the input manageable and still allows for a glider) or use the nicer version.

### Nicer version, 319 bytes

It's still not what I'd call user-friendly, but here's a version I'm actually willing to run:

DIM a(20,20)
1CLS
FOR y=0TO 19
IF j=0THEN INPUT r$FOR x=0TO 19 IF j THEN c=a(x,y)\2 ELSE c=MID$(r$,x+1,1)>"0 a(x,y)=c NEXT x,y CLS FOR y=0TO 19 ? FOR x=0TO 19 ?CHR$(34-a(x,y));
n=0
FOR j=19TO 21
FOR i=19TO 21
n=n-a((x+i)MOD 20,(y+j)MOD 20)MOD 2
NEXT i,j
a(x,y)=2*(n=3)+(1-2*(n=4))*a(x,y)
NEXT x,y
-join(23..42|%{$x=$_;switch(($l[(-23,-22,-21,-1,1,21,22,23|%{$x+$_})]-eq'X').count){2{$l[$x]}3{'X'}default{'.'}}})} sleep 1} Try it online! # PHP, 201 bytes (not tested) for($s=file(f);print"\n";$s=$t)foreach($s as$y=>$r)for($x=-print"
";"
"<$c=$s[$y][++$x];print$t[$y][$x]=" X"[$n<4&$n>2-$a])for($n=-$a=$c>A,$i=$x-!!$x-1;$i++<=$x;)for($k=$y-2;$k++<=$y;)$n+=$s[$k][$i]>A;

Run with -nr.

breakdown

for($s=file(f); # import input from file "f" print"\n"; # infinite loop: 1. print newline$s=$t) # 3. copy target to source, next iteration foreach($s as$y=>$r)                    # 2. loop through lines
for($x=-print"\n";"\n"<$c=$s[$y][++$x]; # print newline, loop$x/$c through line characters (before line break) print # 5. print new cell$t[$y][$x]=" X"[$n>2-$a&$n<4]) # 4. new cell is alive if neighbour count<4 and >2 (>1 if alive) for($n=-                                # 2. init neighbour count: exclude self
$a=$c>A,                            # 1. $a=cell is alife$i=$x-!!$x-1;$i++<=$x;)             # 3. loop $i from one left to one right of current position for($k=$y-2;$k++<=$y;) # loop$k from one above to one below current position
$n+=$s[$k][$i]>A;                       # increase neighbor count if neighbour is alife

# VBA (Excel), 546* Bytes

Sub t()
f=[a1:t20]
For Each c In f.Cells
c.Value=""
r=c.Row
l=c.Column
If g(r,0,0,l,-1,0)Then h=h+1
If g(r,0,0,l,1,21)Then h=h+1
If g(r,-1,0,l,0,0)Then h=h+1
If g(r,1,21,l,0,0)Then h=h+1
If g(r,1,21,l,-1,0)Then h=h+1
If g(r,-1,0,l,1,21)Then h=h+1
If g(r,-1,0,l,-1,0)Then h=h+1
If g(r,1,21,l,1,21)Then h=h+1
If h=3Or(h=2And c.Interior.Color=0)Then c.Value="A"
Next
f.Interior.ColorIndex=0
For Each c In f
If c.Value="A"Then c.Interior.Color=0
Next
End Sub
Function g(r,e,f,c,q,z)
g=(Cells(IIf(r+e=f,Abs(f-20),r+e),IIf(c+q=z,Abs(z-20),c+q)).Interior.Color=0)
End Function

Create the living cells by highlighting cells in A1:T20 and coloring them black.

*When t is run, it executes a single tick. I added a button on mine to click repeatedly. If this doesn't satisfy the requirements, I'll add a do-->while[counta(f)]>0 and a DoEvents for +34 bytes.

[I'll edit this with a link when I upload a copy of my macro-enabled Excel doc]

• This answer appears to be non-functional for a couple of reasons, namely the declaration of f should include a set clause as otherwise f.cells will invoke an object required error as f will be instanciated as a 20 x 20 Array. Secondly, when this is corrected the given solution does not implement the rules of conways game of life properly. I suggest using a simple blinker oscillator as a future test case Feb 15, 2019 at 19:11