# 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

## HTML5 Canvas with JavaScript, 940639586 519 characters

<html><body onload="k=40;g=10;b=[];setInterval(function(){c=[];for(y=k*k;y--;){n=0;for(f=9;f--;)n+=b[(~~(y/k)+k+f%3-1)%k*k+(y+k+~~(f/3)-1)%k];c[y]=n==3||n-b[y]==3;r.fillStyle=b[y]?'red':'tan';r.fillRect(y%k*g,~~(y/k)*g,g-1,g-1)}if(v.nextSibling.checked)b=c},1);v=document.body.firstChild;v.width=v.height=g*k;v.addEventListener('click',function(e){b[~~((e.pageY-v.offsetTop)/g)*k+~~((e.pageX-v.offsetLeft)/g)]^=1},0);r=v.getContext('2d');for(y=k*k;y--;)b[y]=0"><canvas></canvas><input type="checkbox"/>Run</body></html>


I always wanted to do something with canvas, so here is my attempt (original version online). You can toggle cells by clicking (also possible in running mode).

You can now also try the new version here.

Unfortunately there is an issue I couldn't work around yet. The online version is 11 characters longer because jsFiddle puts a text node just before the canvas (why?) and thus the canvas is no longer the first child.

Edit 1: Lots of optimisations and restructurings.

Edit 2: Several smaller changes.

Edit 3: Inlined the complete script block plus minor changes.

• Nice, but change the interval delay to 1 makes it as fast as mine rather than that slow stepping. Also if you want to implement drawing (rather than clicking on each square) you can round the mouse position to the nearest blocksize and fill the rectangle at that point. More characters but more points. Aug 15, 2011 at 0:32
• You can replace new Array('#FFF','#800') with ['#FFF','#800']. Aug 15, 2011 at 15:59
• Though saying that about drawing, my super-golfed doesn't allow drawing and is ugly as sin. Haha. You can set your two colours in the s array to tan and red since they are the two colours with the shortest representations - saves you two chars. Also, if possible, put the literal version of j into the interval. I'm sure there's lots more to squeeze out too. Aug 19, 2011 at 14:46
• @Griffin and Lowjacker: thank you very much. I am also pretty sure that you can golf this much more (and have already some ideas). Unfortunately I didn't find the time to do so. A better golfed version will follow tomorrow - I hope... Aug 19, 2011 at 15:07
• You can remove the html and body tags. It will function the same Mar 8, 2017 at 11:52

## Python, 219 chars

I went for maximum golfage, with just enough interface to satisfy the question.

import time
P=input()
N=range(20)
while 1:
for i in N:print''.join(' *'[i*20+j in P]for j in N)
time.sleep(.1);Q=[(p+d)%400 for d in(-21,-20,-19,-1,1,19,20,21)for p in P];P=set(p for p in Q if 2-(p in P)<Q.count(p)<4)


You run it like this:

echo "[8,29,47,48,49]" | ./life.py


The numbers in the list represent the coordinates of the starting cells. The first row is 0-19, the second row is 20-39, etc.

Run it in a terminal with 21 rows and it looks pretty snazzy.

• This totally should have won. I guess 'ease of input' was weighted fairly high. Aug 3, 2012 at 10:13
• @primo I'd even go so far as to suggest mma should have a separate competition. Jan 26, 2013 at 4:35
• So is this Life of Py then? Mar 10, 2017 at 15:59
• You can always save one more char... 2-(p in P) == 2-({p}<P). But then you would have to change your input to {8,29,47,48,49} :) Aug 17, 2017 at 18:26

# TI-BASIC, 96 bytes (87 for non-competing entry)

For your TI-84 series graphing calculator (!). This was quite a challenge, because there is no easy way to write a buffered graphics routine (definitely nothing built in), and the graph screen has only four relevant graphics commands: Pxl-On(), Pxl-Off(), Pxl-Change(), and pxl-Test().

Uses every accessible pixel on the screen, and wraps correctly. Each cell is one pixel, and the program updates line by line horizontally to the right across the screen. Because the calculators have only a 15MHz z80 processor and BASIC is a slow interpreted language, the code only gets one frame about every five minutes.

User input is easy: before running the program, use the Pen tool to draw your shape on the graph screen.

Adapted from my entry to a code golf contest at the calculator forum Omnimaga.

0
While 1
For(X,0,94
Ans/7+49seq(pxl-Test(remainder(Y,63),remainder(X+1,95)),Y,62,123
For(Y,0,62
If 1=pxl-Test(Y,X)+int(3fPart(3cosh(fPart(6ֿ¹iPart(sum(Ans,Y+1,Y+3
Pxl-Change(Y,X
End
End
End


## Omnimaga version (87 bytes)

This code has an additional feature: it detects if it is being run for the first time, and if randomizes the screen state. In subsequent runs it automatically continues the simulation if stopped after a frame is finished. However, it is not a competing entry because it does not wrap the screen; the cells on the outer border will always be considered dead if the graph screen is cleared beforehand.

0
While 1
For(X,0,93
Ans/7+49seq(pxl-Test(Y,X+1),Y,0,62
For(Y,1,61
If 2rand>isClockOn=pxl-Test(Y,X)+int(3fPart(3cosh(fPart(6ֿ¹iPart(sum(Ans,Y,Y+2
Pxl-Change(Y,X
End
End
ClockOff
End


This version is probably the most golfed code I have ever written, and contains some truly nasty obfuscatory optimizations:

• I use the clock state as a flag. At the start of the program, the date/time clock is enabled, and I use the value of the global isClockOn flag to determine whether it is the first iteration. After the first frame is drawn, I turn the clock off. Saves one byte over the shortest other method and about four over the obvious method.

• I store the states of the three columns next to the one being updated in a 63-element array of base-7 numbers. The 49's place holds the column to the right, the 7's place holds the middle column, and the units place holds the left column--1 for a live cell and 0 for a dead cell. Then I take the remainder mod 6 of the sum of the three numbers around the cell being modified to find the total number of live neighbor cells (it's just like the divisibility by 9 trick—in base 7, the remainder mod 6 equals the sum of the digits). Saves about 10 bytes by itself and gives the opportunity to use the next two optimizations. Example diagram (let's say there is a glider centered at a certain column at Y=45:

Row # | Cell State       | Stored number | Mod 6 = cell count
...
44      Live, Live, Live   49+7+1 = 57     3
...


The center cell will stay dead, because it is surrounded by exactly five live cells.

• After each row is completed, the numbers in the array are updated by dividing the existing numbers by 7, discarding the decimal part, and adding 49 times the values of the cells in the new column. Storing all three columns each time through would be much slower and less elegant, take at least 20 more bytes, and use three lists rather than one, because the values of cells in each row must be stored before cells are updated. This is by far the smallest way to store cell positions.

• The snippet int(3fPart(3cosh( gives 1 when the input equals 3/6, 2 when it equals 4/6, and 0 when it equals 0, 1/6, 2/6, or 5/6. Saves about 6 bytes.

## x86 Assembler, MSDOS, 32 bytes

0xC5 0x24 0x20 0xB3 0x07 0x08 0x04 0xA7 0xC0 0x2D 0x05 0x91 0x02 0x41 0x5E 0x02
0x40 0xFC 0x02 0x80 0x9C 0x00 0x4B 0x75 0xF2 0x8A 0x04 0xF9 0xD2 0xD8 0xEB 0xE1


This code is written in x86 assembler and works in MSDOS. The binary is 32 bytes in size. You can find a very detailed description here. The visible field is 80x25. The output is directly shown on the screen in textmode, which also works as input, so you can enter patterns before you start the program. You can download and comment the intro, you can also test an online version.

lds sp,[si]
X: db 32
mov bl,7                    ; O: 3 iterations
or [si],al                  ; O: Add in new cell
cmpsw
shr byte [di],5             ; O: Shift previous value
C: xchg cx,ax
dec bx                      ; O: Loop back
jnz C
mov al,[si]                 ; O: 3 = birth, 4 = stay (tricky):
stc                         ; O: 1.00?0000x --> 0.0x100?00 (rcr 3)
rcr al,cl                   ; O:          +---> 0.00x100?0 (rcr 4)
jmp short X-1


Mathematica - 333

Features:

• Interactive interface: click cells to make your patterns

• Nice grid

• Buttons: RUN, PAUSE, CLEAR

The code is below.

Manipulate[x=Switch[run,1,x,2,CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},{2,2,2}}},
{1,1}},x],3,Table[0,{k,40},{j,40}]];EventHandler[Dynamic[tds=Reverse[Transpose[x]];
ArrayPlot[tds,Mesh->True]],{"MouseClicked":>(pos=Ceiling[MousePosition["Graphics"]];
x=ReplacePart[x,pos->1-x[[Sequence@@pos]]];)}],{{run,3,""},{1->"||",2->">",3->"X"}}]


If you want to get a feel how this runs, 2nd example in this blog is just a more elaborate version (live Fourier analysis, better interface) of the code above. Example should run right in your browser after free plugin download.

• +1, nice one for having a go. Yeah that's the problem with this site, there are tonnes of old questions which one tends to miss. Jul 31, 2012 at 13:10
• @Griffin thanks for noticing it at all ;) Sep 13, 2013 at 1:35

# C 1063 characters

As a challenge, I did this in C using the golf-unfriendly Windows API for real time IO. If capslock is on, the simulation will run. It will stay still if capslock is off. Draw patterns with the mouse; left click revives cells and right click kills cells.

#include <windows.h>
#include<process.h>
#define K ][(x+80)%20+(y+80)%20*20]
#define H R.Event.MouseEvent.dwMousePosition
#define J R.Event.MouseEvent.dwButtonState
HANDLE Q,W;char*E[3],O;Y(x,y){return E[0 K;}U(x,y,l,v){E[l K=v;}I(){E[2]=E[1];E[1]=*E;*E=E[2];memset(E[1],0,400);}A(i,j,k,l,P){while(1){Sleep(16);for(i=0;i<20;++i)for(j=0;j<20;++j){COORD a={i,j};SetConsoleCursorPosition(Q,a);putchar(E[0][i+j*20]==1?'0':' ');}if(O){for(i=0;i<20;++i)for(j=0;j<20;++j){for(k=i-1,P=0;k<i+2;++k)for(l=j-1;l<j+2;++l){P+=Y(k,l);}U(i,j,1,P==3?1:Y(i,j)==1&&P==4?1:0);}I();}}}main(T,x,y,F,D){for(x=0;x<21;++x)puts("#####################");E[0]=malloc(800);E[1]=E[0]+400;I();I();W=GetStdHandle(-10);Q=GetStdHandle(-11);SetConsoleMode(W,24);INPUT_RECORD R;F=D=O=0;COORD size={80,25};SetConsoleScreenBufferSize(Q,size);_beginthread(A,99,0);while(1){ReadConsoleInput(W,&R,1,&T);switch(R.EventType){case 1:O=R.Event.KeyEvent.dwControlKeyState&128;break;case 2:switch(R.Event.MouseEvent.dwEventFlags){case 1:x=H.X;y=H.Y;case 0:F=J&1;D=J&2;}if(F)U(x,y,0,1);if(D)U(x,y,0,0);}}}


The compiled EXE can be found here

Edit: I've commented up the source. It's available Here

• I'd love to see a commented version of this! Dec 21, 2012 at 2:50
• Sure, if I can remember what I was thinking... =p Dec 22, 2012 at 23:18
• @luserdroog Here it is pastebin.com/BrX6wgUj Dec 22, 2012 at 23:59
• This is just awesome. Dec 12, 2016 at 22:07

# J (39 characters)

l=:[:+/(3 4=/[:+/(,/,"0/~i:1)|.])*.1,:]


Based on this APL version (same algorithm, toroidal convolution).

Example usage:

   r =: (i.3 3) e. 1 2 3 5 8
r
0 1 1          NB. A glider!
1 0 1
0 0 1

R =: _1 _2 |. 5 7 {. r
R
0 0 0 0 0 0 0  NB. Test board
0 0 0 1 1 0 0
0 0 1 0 1 0 0
0 0 0 0 1 0 0
0 0 0 0 0 0 0

l R
0 0 0 0 0 0 0  NB. Single step
0 0 0 1 1 0 0
0 0 0 0 1 1 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0


## Mathematica, 123 characters

A very rudimentary implementation that doesn't use Mathematica's built-in CellularAutomaton function.

ListAnimate@NestList[ImageFilter[If[3<=Total@Flatten@#<=3+#[[2]][[2]],1,0]&,#,1]&,Image[Round/@RandomReal[1,{200,200}]],99]


# Vim, 549552533421420 bytes

Nice.

+3 because of a bug where cells wouldn't die if no cells came to life.

-19 because I made a version that was generalized to any grid size and realized that I accidentally golfed it.

-112 bytes because of whatnot and hornswoggling.

-1 byte because yes.

Go0
if "<C-v><C-v><C-v><C-r>""=="<Esc>^"zC<C-v><C-v><C-v>
norm <Esc>^"yC<C-v><C-v><C-v>
en<C-v><C-v><Esc>^"xCyl'm:<C-r>z@"||"<C-v><C-r>""=="o"<C-r>y<C-v><C-v><C-v><C-a><C-r>x
<Esc>^"iC'm"mylcyl:<C-r>z "&&<C-v><C-r>m==3<C-r>yr+<C-v>
else<C-r>z@"&&<C-v><C-r>m<2<C-r>yro<C-v>
else<C-r>z@"&&<C-v><C-r>m>3<C-r>yro<C-r>x
<Esc>^"aCchyl:<C-r>z#"<C-r>y$h<C-r>x mc<Esc>^"hCcjyl:<C-r>z#"<C-v> cal cursor(2,col('.'))<C-r>x mc<Esc>^"jCckyl:<C-r>z#"<C-v> cal cursor(line('$')-2,col('.'))<C-r>x
mc<Esc>^"kCclyl:<C-r>z#"<C-r>y0l<C-r>x
mc<Esc>^"lC yl:<C-r>z!"<C-v>
%s/[+@]/@/g<C-v>
%s/o/ /g<C-v>
k<C-v>
else<C-r>z<BS><BS><BS>!="#" <C-r>ymc'mr0c@h@i@k@i@l@i@l@i@j@i@j@i@h@i@h@i@k@l@a<C-r>x
@e<Esc>0"eDddmm


Try it online!

This was fun.

The input in the TIO is (obviously) the GoL grid. You can place living tiles as @, and each gg @e in the footer is a single step, so you can add or remove them as you want to see different iterations of the board.

For each cell in the grid, it goes to all of the surrounding tiles, wrapping if it hits a #, and if the tile is @ (alive) or o (about to die), it increments the counter. Depending on what the counter is after checking each surrounding tile, it marks the cell to live or die, or do nothing. After checking each tile in the grid, it replaces all of the + with @ and all of the o with  . It's a bit slow, but on TIO, it's a bit faster than on my machine, which is nice.

This also works for any grid size, including rectangular grids.

• Just one byte from greatness D: Sep 23, 2021 at 16:59
• @RedwolfPrograms You were saying? :P Sep 23, 2021 at 17:24
• @AaroneousMiller Niceeee May 14 at 17:55

## Scala, 118111581128106310181003999992 987 characters

import swing._
import event._
object L extends SimpleSwingApplication{import java.awt.event._
import javax.swing._
var(w,h,c,d,r)=(20,20,20,0,false)
var x=Array.fill(w,h)(0)
def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
def top=new MainFrame with ActionListener{preferredSize=new Dimension(500,500)
reactions+={case ButtonClicked(c)=>r= !r}}}}}
contents=new Component{listenTo(mouse.clicks)
reactions+={case e:MouseClicked=>var p=e.point
x(p.x/c)(p.y/c)^=1
repaint}
override def paint(g:Graphics2D){for(j<-0 to h-1;i<-0 to w-1){var r=new Rectangle(i*c,j*c,c,c)
x(i)(j)match{case 0=>g draw r
case 1=>g fill r}}}}
def actionPerformed(e:ActionEvent){if(r){var t=x.map(_.clone)
for(j<-0 to h-1;i<-0 to w-1){d=0
n(i,j)
x(i)(j)match{case 0=>if(d==3)t(i)(j)=1
case 1=>if(d<2||d>3)t(i)(j)=0}}
x=t.map(_.clone)
repaint}}
val t=new Timer(200,this)
t.start}}


Ungolfed:

import swing._
import event._

object Life extends SimpleSwingApplication
{
import java.awt.event._
import javax.swing._
var(w,h,c,d,run)=(20,20,20,0,false)
var x=Array.fill(w,h)(0)
def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
def top=new MainFrame with ActionListener
{
title="Life"
preferredSize=new Dimension(500,500)
{
{
{
listenTo(this)
reactions+=
{
case ButtonClicked(c)=>run= !run
}
}}
}
}
contents=new Component
{
listenTo(mouse.clicks)
reactions+=
{
case e:MouseClicked=>
var p=e.point
if(p.x<w*c)
{
x(p.x/c)(p.y/c)^=1
repaint
}
}
override def paint(g:Graphics2D)
{
for(j<-0 to h-1;i<-0 to w-1)
{
var r=new Rectangle(i*c,j*c,c,c)
x(i)(j) match
{
case 0=>g draw r
case 1=>g fill r
}
}
}
}
def actionPerformed(e:ActionEvent)
{
if(run)
{
var t=x.map(_.clone)
for(j<-0 to h-1;i<-0 to w-1)
{
d=0
n(i,j)
x(i)(j) match
{
case 0=>if(d==3)t(i)(j)=1
case 1=>if(d<2||d>3)t(i)(j)=0
}
}
x=t.map(_.clone)
repaint
}
}
val timer=new Timer(200,this)
timer.start
}
}


The larger part of the code here is Swing GUI stuff. The game itself is in the actionPerformed method which is triggered by the Timer, and the helper function n which counts neighbours.

Usage:

Compile it with scalac filename and then run it with scala L.
Clicking a square flips it from live to dead, and the menu option starts and stops the game. If you want to change the size of the grid, change the first three values in the line: var(w,h,c,d,r)=(20,20,20,0,false) they are width, height and cell size (in pixels) respectively.

• I found 2 golfing-improvements: import java.awt.event._ and contents+=m("Go",true)+=m("Stop",false)}}, leading to 1093 characters. Aug 14, 2011 at 19:20
• @user unknown Thanks. I found a few improvements myself - down to 1063 now. Aug 14, 2011 at 19:47
• Damn you've been busy. Keep it up! I will be testing answers when a few more people post them. Aug 14, 2011 at 23:56

## Ruby 1.9 + SDL (380325 314)

EDIT: 314 characters, and fixed a bug with extra cells appearing alive on the first iteration. Upped the grid size to 56 since the color routine only looks at the lowest 8 bits.

EDIT: Golfed down to 325 characters. Grid width/height is now 28 since 28*9 is the largest you can have while still using the value as the background colour. It also processes only one SDL event per iteration now, which obviates the inner loop completely. Pretty tight I think!

The simulation starts paused, with all cells dead. You can press any key to toggle pause/unpause, and click any cell to toggle it between alive and dead. Runs an iteration every tenth of a second.

The wrapping is a bit wonky.

require'sdl'
SDL.init W=56
R=0..T=W*W
b=[]
s=SDL::Screen.open S=W*9,S,0,0
loop{r="#{e=SDL::Event.poll}"
r['yU']?$_^=1:r[?Q]?exit: r['nU']?b[e.y/9*W+e.x/9]^=1:0 b=R.map{|i|v=[~W,-W,-55,-1,1,55,W,57].select{|f|b[(i+f)%T]}.size;v==3||v==2&&b[i]}if$_
R.map{|i|s.fillRect i%W*9,i/W*9,9,9,[b[i]?0:S]*3}
s.flip
sleep 0.1}


Looks like this:

Fun challenge! I welcome any improvements anybody can see.

• Nice try but I can see straight away that you've gone wrong. You can't have a pattern like that in GoL. Have another read of the rules: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules Aug 1, 2012 at 8:01
• @Griffin I think the screenshot was taken after pausing and toggling some cells manually - I'll check the rules again, though. Thanks! Aug 2, 2012 at 0:44
• @Griffin cant the seed pattern be in any possible configuration? Aug 8, 2012 at 4:30

# Pure Bash, 244 bytes

Works on a toroidally-wrapped 36x24 universe:

mapfile a
for e in {0..863};{
for i in {0..8};{
[ "${a[(e/36+i/3-1)%24]:(e+i%3-1)%36:1}" == O ]&&((n++)) } d=\ c=${a[e/36]:e%36:1}
[ "$c" == O ]&&((--n==2))&&d=O ((n-3))||d=O b[e/36]+=$d
n=
}
printf -vo %s\\n "${b[@]}" echo "$o"
exec $0<<<"$o"


Since this is a shell script, the method of input is congruent with other shell commands - i.e. from stdin:

$./conway.sh << EOF O O OOO EOF O O OO O O O O OO  ... etc We can redirect input from any text source, piped through a tr filter to get interesting initial generations, e.g. man tr | tr [:alnum:] O | ./conway.sh  # ><>, 284 bytes 0fv$ @$0$+1~<
+$>i:1+ ?!v:a=?^}$:@@:@{@p$1 @@:@(?$ &$>~&l1=?v: v f0-e&< v> > >$:{:}=?v:1+@$:@}}000102101220212280& ^v?=+f}}@:{{:+1$0~<
>:1-$?!v@${:}+1-${{:@}}+1-l2-[f-{{:@}}:@+$%f+${:}:@+$%$]g"!"=&+&$@:${{~/]$r[5{{+" "+*@=3@=2:&="!"g}}@:
~~<00  v!?-4lf0]rpr[-2l~~


Try it at https://suppen.no/fishlanguage!

It takes the initial configuration as input, and uses a wrapping grid of the inputted size. Here's an example grid for a glider:

v   v
!
!
!!!
v   v


 s and vs are dead cells (vs can be used instead of  s to avoid truncation), and !s are alive cells. The lines don't have to be of the same size; the maximum length will be used.

Here's a Gosper glider gun: (this takes a while)

v                       !                          v
! !
!!      !!            !!
!   !    !!            !!
!!        !     !   !!
!!        !   ! !!    ! !
!     !       !
!   !
!!

v                                                  v


It stores the input in the program grid and applies changes in place, so the current state can be seen in a visual interpreter like https://suppen.no/fishlanguage

C# - 675 chars

I've always wanted to write a version of this program. Never knew it would only take a lazy half hour for a quick and dirty version. (Golfing it takes much longer, of course.)

using System.Windows.Forms;class G:Form{static void Main(){new G(25).ShowDialog();}
public G(int z){var g=new Panel[z,z];var n=new int [z,z];int x,y,t;for(int i=0;i<z;
i++)for(int j=0;j<z;j++){var p=new Panel{Width=9,Height=9,Left=i*9,Top=j*9,BackColor
p);}KeyUp+=(s,_)=>{for(int i=0;i<99;i++){for(x=0;x<z;x++)for(y=0;y<z;y++){t=0;for(int
c=-1;c<2;c++)for(int d=-1;d<2;d++)if(c!=0||d!=0){int a=x+c,b=y+d;a=a<0?24:a>24?0:a;b=
b<0?24:b>24?0:b;t+=g[a,b].Visible?0:1;}if(t==3||t>1&&!g[x,y].Visible)n[x,y]=1;if(t<2
||t>3)n[x,y]=0;}for(x=0;x<z;x++)for(y=0;y<z;y++)g[x,y].Visible=n[x,y]<1;Update();}};}}


Usage

• Enter a starting pattern by clicking cells to turn them on (alive).
• Start the game by pressing any keyboard key.
• The game runs for 99 generations every time a key is pressed (I could have made it 9 to save a char, but that seemed too lame).

Golfing compromises

• You can only turn cells on with the mouse, not off, so if you make a mistake you have to restart the program.
• There are no grid lines, but that doesn't hurt playability too much.
• Update speed is proportional to CPU speed, so on very fast computers it will probably be just a blur.
• Living cells are red because "black" uses 2 more characters.
• The smallness of the cells and the fact that they don't use up all the form space are also character-saving compromises.

## JavaScript, 130

Not totally responding to the challenge, but for the record, here's a Game of Life engine in 130 bytes made by Subzey and I in 2013.

http://xem.github.io/miniGameOfLife/

/* Fill an array with 0's and 1's, and call g(array, width, height) to iterate */
g=function(f,c,g,d,e,b,h){g=[];e=[c+1,c,c-1,1];for(b=c*c;b--;g[b]=3==d||f[b]&&2==d,d=0)for(h in e)d+=f[b+e[h]]+f[b-e[h]];return g}

• This seems to have some problems with the first row. For example setting @@\n@@ (2 by 2 square in top left corner) or .@\n.@\n.@. (1 by 3 column) Feb 5, 2018 at 21:03

# Mathematica, 115 bytes

Here's an easy cop-out to this:

ListAnimate[ArrayPlot/@CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},
{2,2,2}}},{1,1}},{RandomInteger[1,{9,9}],0},90]]

• Mathematica is fine, but as the rules state the program must allow the user to input their own patterns. This rule is intentional since a few languages allow short implementations like this but with no user interaction. Sure you can put your own array in there, but it's not gonna win. Aug 14, 2011 at 23:58
• "input" in Mathematica is mostly through the notebook interface, so I don't think "user interaction" is really possible. You just replace the RandomInteger argument to the CellularAutomaton function with whatever you want, and re-evaluate the code. Aug 15, 2011 at 0:16
• User interaction is possible. The most simplistic method I can think of right now is an array of buttons. Give it a go man. Aug 15, 2011 at 0:19

# Java (OpenJDK 8) - 400 388 367 bytes

Second and (probably) Final Edit: Managed to golf an extra 21 bytes after finding these (imo) goldmines - definitely recommend new people to read these (especially if you're going to try some of these challenges using Java).

Resulting code (probably going to end up golfing even more if I find out how to shorten those double nested for loops...):

u->{int w=u.length,h=u[0].length,x,y,i,j,n;Stack<Point>r=new Stack<Point>();for(;;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x)for(y=0;y<h;++y){boolean o=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}


Try it online!

(Original post starts here.)

I actually thought for a moment that I would be able to at least challenge the best Python answer with my (arguably limited) knowledge of Java lol...It was a challenge I nevertheless enjoyed partaking in (despite having joined the party perhaps just a little bit late...)

There's not much to it really - basic explanation as follows (ungolfed):

/*
* Explanation of each variable's usage:
* w=height* of array
* h=width* of array
* x=y* coord of point in array
* y=x* coord of point in array
* i and j are counters for calculating the neighbours around a point in the array
* n=neighbour counter
* r=temporary array to store the cells from the current generation
* u=the 2d array used for all the calculations (parameter from lambda expression)
* c=temporary variable used to help populate the 2d array
* o=boolean variable that stores the value of whether the cell is alive or not
*/
u-> // start of lambda statement with u as parameter (no need for brackets as it's only one parameter being passed)
{
int w=u.length,h=u[0].length,x,y,i,j,n; // defines all the necessary integer variables;
Stack<Point>r=new Stack<Point>(); // same with the only array list needed (note how I only use two data structures);
for(;;) // notice how this is still an infinite loop but using a for loop;
{
for(Point c:r)u[c.x][c.y]=1; //for every point in the "previous" generation, add that to the 2D array as a live (evil?) cell;
r.clear(); // clears the array list to be populated later on
for(x=0;x<w;++x) // a pair of nested for loops to iterate over every cell of the 2D array;
{
for(y=0;y<h;++y)
{
// sets o to be the presence of a live cell at (x,y) then uses said value in initialising the neighbour counter;
boolean o=u[x][y]>1;n=o?-1:0;
for(i=-2;++i<2;) // another pair of nested for loops - this one iterates over a 3x3 grid around *each* cell of the 2D array;
{                // this includes wrap-around (note the modulus sign in the if statement below);
for(j=-2;++j<2;)
{
if(u[(w+x+i)%w][(h+y+j)%h]>0)++n; // this is where the first interesting thing lies - the bit which makes wrap-around a reality;
}
}
if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y)); // this is the second interesting bit of my code - perhaps more so as I use bitwise operators to calculate the number of neighbours (x,y) has;
// (since I'm technically dealing with 0s and 1s, it's not a total misuse of them imo);
System.out.print(u[x][y]+(y>h-2?"\n":""));  // that extra part of the print statement adds a newline if we reached the end of the current 'line';
}
}
// since the information about the new generation is now in the array list, this array can be emptied out, ready to receive said info on the new generation;
for(int[]t:u)Arrays.fill(t,0);
}
} // end of lambda statement


Yes, there's a catch with my approach.

As most of you probably noticed, my golfed code as it currently stands will loop forever. To prevent this, a counter can be introduced at the top and used in the while loop to only display n (in this case, 5) iterations as follows (notice the new b variable added):

u->{int b=0,w=u.length,h=u[0].length,x,y,i,j,n;Stack<Point>r=new Stack<Point>();for(;++b<6;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x)for(y=0;y<h;++y){boolean o=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}


Additionally, a few points worth mentioning. This program does not check if the input is correct and will, therefore, fail with (most likely) an ArrayOutOfBoundsException; as such, make sure to check that the input is valid by completely filling in a part of an array (skewered arrays will throw the exception mentioned above). Also, the board as it currently is looks 'fluid' - that is, there is no separation between one generation and the next. If you wish to add that in to double-check that the generations being produced are indeed valid, an extra System.out.println(); needs to be added just before for(int[]t:u)Arrays.fill(t,0); (see this Try it online! for clarity). And last, but not least, given that this is my first code golf, any feedback is greatly appreciated :)

Old code from previous 388 byte answer:

u->{int w=u.length,h=u[0].length,x,y,i,j,n;ArrayList<Point>r=new ArrayList<Point>();while(true){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}for(int[]t:u)Arrays.fill(t,0);}}


And from the initial 400 byte answer:

int w=35,h=20,x,y,i,j,n;ArrayList<Point>l=new ArrayList<Point>(),r;while(true){int[][]u=new int[w][h];for(Point c:l)u[c.x][c.y]=1;r=new ArrayList<Point>();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}l.clear();l.addAll(r);}

• Amazing first post, welcome to PPCG! Aug 14, 2017 at 1:20
• Thanks, I'm definitely going to be doing more of these - they're fun :) Aug 14, 2017 at 1:26
• Join us, we have Dennis. Also, this is not a complete program nor a function, which it needs to be, IIRC. Aug 14, 2017 at 1:28
• Oh right forgot the 'program' part :P Editing that in in a bit. Aug 14, 2017 at 2:04
• It can just be a function too. Aug 14, 2017 at 2:06

# Stencil, 6 bytes

Not my favourite language, but it is short…

4 code bytes plus the ∊nlist and Torus flags.

3∊me


Try it online!

Is…
3 3
∊ a member of
m the moore-neighbourhood-count with self or
e the moore-neighbourhood-count without self
…?

# R, 149 144 bytes

function(m)repeat{image(m)
p=apply(which(m|1,T),1,function(j)sum(m[t((j+t(which(m[1:3,1:3]|1,T)-3))%%20)+1]))
a=p==3|m&p==4;m[]=0;m[a]=1
scan()}


Try it online!

(Note that TIO version swaps image for print so that output is visible, and reduces the grid size to 12x12 to fit into the browser window)

Well, the challenge is still open so I guess it must be Ok to submit almost 9 years late! And there hasn't been an R submission yet.

The function is called using the full starting pattern in the form of a 20x20 matrix, and it then steps forward once every time the return key is pressed. Output is quite pretty using the R image function, or (for the same number of characters) quite ugly using only 1s and 0s.

Commented:

game_of_life=function(m)        # Input m as starting state,
repeat{                     # Repeat...
image(m)                # Draw grid of current state;
p=                      # Find p =number of live neighbours (including self):
apply(which(m|1,T),1,   # loop over coordinates of grid...
function(j)sum(     # getting sums of...
m[                  # live cells at...
t((j+               # this coordinate...
t(which(m[1:3,1:3]|1,T)-3))
# plus offsets -1 to surrounding neighbours
# (including itself)...
%%20)               # modulo the size of the grid (20)...
+1]))               # plus 1 (to get 1-based coordinates)
a=p==3|m&p==4;          # set cells with 3 live neighbours (including self)
m[]=0;m[a]=1            # or 4 (if already alive) to 1;
# all others to 0.
scan()}                 # Wait for user input before next round


This is a code-golf implementation, which admittedly rather sacrifices ease-of-input (the TIO example demonstrates how to easily set-up a glider flying across the grid).

For an extra 13 bytes byte (145 total), it can be bloated improved to accept an unlimited-sized starting matrix, with the dimensions specified as an additional argument (here).

### GW-BASIC, 1086 1035 bytes (tokenised)

In tokenised form, this is 1035 bytes. (The ASCII form is, of course, a bit longer.) You get the tokenised form by using the SAVE"life command without appending ",a in the interpreter.

10 DEFINT A-Z:DEF SEG=&HB800:KEY OFF:COLOR 7,0:CLS:DEF FNP(X,Y)=PEEK((((Y+25)MOD 25)*80+((X+80)MOD 80))*2)
20 X=0:Y=0
30 LOCATE Y+1,X+1,1
40 S$=INKEY$:IF S$=""GOTO 40 50 IF S$=CHR$(13)GOTO 150 60 IF S$=" "GOTO 130
70 IF S$=CHR$(0)+CHR$(&H48)THEN Y=(Y-1+25)MOD 25:GOTO 30 80 IF S$=CHR$(0)+CHR$(&H50)THEN Y=(Y+1)MOD 25:GOTO 30
90 IF S$=CHR$(0)+CHR$(&H4B)THEN X=(X-1+80)MOD 80:GOTO 30 100 IF S$=CHR$(0)+CHR$(&H4D)THEN X=(X+1)MOD 80:GOTO 30
110 IF S$="c"THEN CLS:GOTO 20 120 GOTO 40 130 Z=PEEK((Y*80+X)*2):IF Z=42 THEN Z=32ELSE Z=42 140 POKE(Y*80+X)*2,Z:GOTO 40 150 LOCATE 1,1,0:ON KEY(1)GOSUB 320:KEY(1) ON 160 V!=TIMER+.5:FOR Y=0 TO 24:FOR X=0 TO 79:N=0 170 Z=FNP(X-1,Y-1):IF Z=42 OR Z=46 THEN N=N+1 180 Z=FNP(X,Y-1):IF Z=42 OR Z=46 THEN N=N+1 190 Z=FNP(X+1,Y-1):IF Z=42 OR Z=46 THEN N=N+1 200 Z=FNP(X-1,Y):IF Z=42 OR Z=46 THEN N=N+1 210 Z=FNP(X+1,Y):IF Z=42 OR Z=46 THEN N=N+1 220 Z=FNP(X-1,Y+1):IF Z=42 OR Z=46 THEN N=N+1 230 Z=FNP(X,Y+1):IF Z=42 OR Z=46 THEN N=N+1 240 Z=FNP(X+1,Y+1):IF Z=42 OR Z=46 THEN N=N+1 250 Z=PEEK((Y*80+X)*2):IF Z=32 THEN IF N=3 THEN Z=43 260 IF Z=42 THEN IF N<2 OR N>3 THEN Z=46 270 POKE(Y*80+X)*2,Z:NEXT:NEXT:FOR Y=0 TO 24:FOR X=0 TO 79:Z=PEEK((Y*80+X)*2):IF Z=46 THEN Z=32 280 IF Z=43 THEN Z=42 290 POKE(Y*80+X)*2,Z:NEXT:NEXT 300 IF TIMER<V!GOTO 300 310 IF INKEY$=""GOTO 160
320 SYSTEM


This is the maximum-golfed version, but still featureful: upon starting, you get an editor, in which you can move with the cursor keys; space toggles bacteria on/off on the current field, c clears the screen, Return starts game mode.

Here follows a less-obfuscated version, which also sets an initial game board with two structures (a circulary-rotating thing and a glider):

1000 REM Conway's Game of Life
1001 REM -
1002 REM Copyright (c) 2012 Thorsten "mirabilos" Glaser
1004 REM -
1005 DEFINT A-Z:DEF SEG=&hB800
1006 KEY OFF:COLOR 7,0:CLS
1007 DEF FNP(X,Y)=PEEK((((Y+25) MOD 25)*80+((X+80) MOD 80))*2)
1010 PRINT "Initial setting mode, press SPACE to toggle, RETURN to continue"
1020 PRINT "Press C to clear the board, R to reset. OK? Press a key then."
1030 WHILE INKEY$="":WEND 1050 CLS 1065 DATA 3,3,4,3,5,3,6,3,7,3,8,3,3,4,4,4,5,4,6,4,7,4,8,4 1066 DATA 10,3,10,4,10,5,10,6,10,7,10,8,11,3,11,4,11,5,11,6,11,7,11,8 1067 DATA 11,10,10,10,9,10,8,10,7,10,6,10,11,11,10,11,9,11,8,11,7,11,6,11 1068 DATA 4,11,4,10,4,9,4,8,4,7,4,6,3,11,3,10,3,9,3,8,3,7,3,6 1069 DATA 21,0,22,1,22,2,21,2,20,2,-1,-1 1070 RESTORE 1065 1080 READ X,Y 1090 IF X=-1 GOTO 1120 1100 POKE (Y*80+X)*2,42 1110 GOTO 1080 1120 X=0:Y=0 1125 LOCATE Y+1,X+1,1 1130 S$=INKEY$1140 IF S$="" GOTO 1130
1150 IF S$=CHR$(13) GOTO 1804
1160 IF S$=" " GOTO 1240 1170 IF S$=CHR$(0)+CHR$(&h48) THEN Y=(Y-1+25) MOD 25:GOTO 1125
1180 IF S$=CHR$(0)+CHR$(&h50) THEN Y=(Y+1) MOD 25:GOTO 1125 1190 IF S$=CHR$(0)+CHR$(&h4B) THEN X=(X-1+80) MOD 80:GOTO 1125
1200 IF S$=CHR$(0)+CHR$(&h4D) THEN X=(X+1) MOD 80:GOTO 1125 1210 IF S$="c" THEN CLS:GOTO 1120
1220 IF S$="r" GOTO 1050 1225 IF S$=CHR$(27) THEN END 1230 GOTO 1130 1240 Z=PEEK((Y*80+X)*2) 1250 IF Z=42 THEN Z=32 ELSE Z=42 1260 POKE (Y*80+X)*2,Z 1270 GOTO 1130 1804 LOCATE 1,1,0 1900 ON KEY(1) GOSUB 2300 1910 KEY(1) ON 2000 V!=TIMER+.5 2010 FOR Y=0 TO 24 2020 FOR X=0 TO 79 2030 N=0 2040 Z=FNP(X-1,Y-1):IF Z=42 OR Z=46 THEN N=N+1 2050 Z=FNP(X ,Y-1):IF Z=42 OR Z=46 THEN N=N+1 2060 Z=FNP(X+1,Y-1):IF Z=42 OR Z=46 THEN N=N+1 2070 Z=FNP(X-1,Y ):IF Z=42 OR Z=46 THEN N=N+1 2080 Z=FNP(X+1,Y ):IF Z=42 OR Z=46 THEN N=N+1 2090 Z=FNP(X-1,Y+1):IF Z=42 OR Z=46 THEN N=N+1 2100 Z=FNP(X ,Y+1):IF Z=42 OR Z=46 THEN N=N+1 2110 Z=FNP(X+1,Y+1):IF Z=42 OR Z=46 THEN N=N+1 2120 Z=PEEK((Y*80+X)*2) 2130 IF Z=32 THEN IF N=3 THEN Z=43 2140 IF Z=42 THEN IF N<2 OR N>3 THEN Z=46 2150 POKE (Y*80+X)*2,Z 2160 NEXT X 2170 NEXT Y 2200 FOR Y=0 TO 24 2210 FOR X=0 TO 79 2220 Z=PEEK((Y*80+X)*2) 2230 IF Z=46 THEN Z=32 2240 IF Z=43 THEN Z=42 2250 POKE (Y*80+X)*2,Z 2260 NEXT X 2270 NEXT Y 2280 IF TIMER<V! GOTO 2280 2290 IF INKEY$="" GOTO 2000
2300 SYSTEM


I wrote this in 15 minutes while bored and waiting for a friend, who was code-golfing with his “apprentice” for Conway’s Game of Life at the same time.

It functions like this: It immediately uses the 80x25 text mode screen buffer (change the initial DEF SEG to use &hB000 if you’re on a Hercules graphics card; these settings work with Qemu and (slower) dosbox). An asterisk * is a bacterium.

It works two-pass: first, birthplaces are marked with + and death marks its targets with .. In the second pass, + and . are replaced with * and  , respectively.

The TIMER thing is to make it wait for half a second after each round, in case your Qemu host is very fast ☺

I’m not hoping for a shortest-wins price here but for a coolness one, especially considering the initial board setup. I’ve also got a version where the game engine was replaced by assembly code, in case you’re interested…

• Considering you incremented your labels by 1 on the non-golfed version, is it possible to do the same on the golfed version? (i.e., 1, 2, 3, etc.) Or do the line numbers not count? Aug 17, 2017 at 20:12
• line numbers, when tokenised, count as word (16 bit), if I’m not totally mistaken Aug 18, 2017 at 0:23
• Okay then, guess I must've been thinking of some other BASIC dialect then. Aug 18, 2017 at 10:51
• @Zacharý Click on “GW-BASIC tokenised program format” then on “Program format” here to see that, indeed, line numbers are constantly two bytes, and for more in-depth details on the token format. Aug 22, 2017 at 8:48

# J, 45

I thought I'd give J a try. It's not particularly well golfed yet, but I'll give it another try soon.

(]+.&(3&=)+)+/((4&{.,(_4&{.))(>,{,~<i:1))&|.


Example:

   f =: 5 5 $0 1 0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 f 0 1 0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 f (]+.&(3&=)+)+/((4&{.,(_4&{.))(>,{,~<i:1))&|. f 0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0  # Processing536 532 int h=22,t=24,i,j;int[][]w=new int[t][t],b=new int[t][t];int[]q={1,0,-1};void draw(){if(t<9){clear();for(i=2;i<h;i++){for(j=2;j<h;j++)w[i][j]=b[i][j];w[i][1]=w[i][21];w[i][h]=w[i][2];w[1][i]=w[21][i];w[h][i]=w[2][i];}for(i=1;i<23;i++)for(j=1;j<23;j++){t=-w[i][j];for(int s:q)for(int d:q)t+=w[i+s][j+d];b[i][j]=w[i][j]>0&(t<2|t>3)?0:t==3?1:b[i][j];}a();}}void keyPressed(){t=0;}void mousePressed(){int i=mouseX/5+2,j=mouseY/5+2;w[i][j]=b[i][j]=1;a();}void a(){for(i=0;i<h-2;i++)for(j=0;j<h-2;j++)if(w[i+2][j+2]==1)rect(i*5,j*5,5,5);}  I believe this satisfies all of the requirements. Ungolfed: int h=22,t=24,i,j; int[][]w=new int[t][t],b=new int[t][t]; int[]q={1,0,-1}; void draw(){ if(t<9){ clear(); for(i=2;i<h;i++){ for(j=2;j<h;j++) w[i][j]=b[i][j]; w[i][1]=w[i][21]; w[i][h]=w[i][2]; w[1][i]=w[21][i]; w[h][i]=w[2][i]; } for(i=1;i<23;i++) for(j=1;j<23;j++){ t=-w[i][j]; for(int s:q) for(int d:q) t+=w[i+s][j+d]; b[i][j]=w[i][j]>0&(t<2|t>3)?0:t==3?1:b[i][j]; } a(); } } void keyPressed(){ t=0; } void mousePressed(){ int i=mouseX/5+2,j=mouseY/5+2; w[i][j]=b[i][j]=1; a(); } void a(){ for(i=0;i<h-2;i++) for(j=0;j<h-2;j++) if(w[i+2][j+2]==1) rect(i*5,j*5,5,5); }  # Perl, 218216211 202 bytes $,=$/;$~=AX3AAAx76;$b=pack('(A79)23',<>)x6;{print unpack'(a79)23a0',$b;select$v,$v,$v,0.1;$b=pack'(A)*',unpack'((x7a/(x13)X4Ax!18)1817@0)4',pack'((a*)17xx!18)*',unpack"x1737(AA$~Ax$~AA$~@)2222",$b;redo}


(No newline at the end of this code.)

Reads the starting pattern from standard input, as a text file where live cells are represented as 1, dead cells represented as a space, lines are separated by a newline. The input shall not have characters other than these. Lines can be variable length, and will be padded or truncated to exactly 79 wide. Example input is a glider gun:

                                  1
1 1
11      11            11
1   1    11            11
11        1     1   11
11        1   1 11    1 1
1     1       1
1   1
11

11
1
111
1


As the program runs Game of Life, every state is dumped to the standard output in a format similar to the input, then delays 0.1 seconds. The delay can be customized by changing the fourth argument of the select call.

The game board is hard-coded to size 79x23. It is wrapped in a torus: if you leave the board on the bottom, you end up at the top; if you leave on the right side, you end up at the left side but shifted one row down.

Here's an alternate version that doesn't read any input and starts from a random board:

$,=$/;$/=AX3AAAx76;$b=pack("(A)*",map{rand 3<1}0..1816)x6;{print unpack'(a79)23a0',$b;select$v,$v,$v,0.1;$b=pack'(A)*',unpack'((x7a/(x13)X4Ax!18)1817@0)4',pack'((a*)17xx!18)*',unpack"x1737(AA$/Ax$/AA$/@)2222",$b;redo}  This code is derived from an obfuscated game of life perl program I wrote years ago. I have changed it a lot to make the board toroidal and golf the code. This is probably not the shortest method to implement Game of Life in perl, but it's one of the less comprehensible ones. The board is stored in $b as a string of '1' and ' ', one for each cell, only the whole thing is repeated at least three times. The third unpack call extracts 17 values for each cell: there's one for the cell itself and two for each of the eight neighboring cells, in an arbitrary order, and each value is '1' or an empty string. The cell should be live in the next iteration iff the number of '1' values among these 17 values is 5, 6, or 7. The third pack call concatenates these 17 values to a 18 character wide field left aligned and padded with nul bytes on the right. The second unpack call takes such a 18 wide field, dispatches on the character at position 7, unpacks the space from position 17 if it's a '1', or unpacks the character from position 4 otherwise. This result is exactly the value the cell should have in the next generation.

# C 811806800783 753 Bytes

#define S(y) SDL_##y;
#define s unsigned
#define u s char
#define _ g[i*256+j]
#define L for(s i=0;i<256;i++)for(s j=0;j<256;j++)
#include <SDL2/SDL.h>
struct __attribute__((__packed__)){u l:1;u n:7;}g[1<<16];main(u k, u** v){S(Window*w)S(Renderer*r)S(Texture*t)uint32_t p[1<<16];S(CreateWindowAndRenderer(256,256,0,&w,&r))t=S(CreateTexture(r,372645892,1,256,256))read(open(v[1],0),g,1<<16);for(;;){L _.n=g[((u)(i-1))*256+((u)(j-1))].l+g[((u)(i-1))*256+j].l+g[((u)(i-1))*256+(u)(j+1)].l+g[(i<<8)+(u)(j-1)].l+g[(i*256)+(u)(j+1)].l+g[((u)(i+1))*256+((u)(j-1))].l+g[((u)(i+1))*256+j].l+g[((u)(i+1))*256+(u)(j+1)].l;L _.l=(_.n==3||_.l&&_.n==2);for(s i=0;i<1<<16;i++){p[i]=(g[i].l<<7);}S(UpdateTexture(t,0,p,1024))S(RenderCopy(r,t,0,0))S(RenderPresent(r))}}


this one might be "overkill" for being 255x255 instead of just 20, but this way I didn't have to bound check and could just cast instead

## To compile & run:

cc gol.c -lsdl2
./a.out /path/to/seed


## To seed it:

Specify a file, the contents of the file will be read into the graph, and only the least-significant bit actually matters, I would recommend using /dev/urandom

Scala - 799 chars

Run as a script. A mouse click on a square toggles it on or off and any key starts or stops generation.

import java.awt.Color._
import swing._
import event._
import actors.Actor._
new SimpleSwingApplication{var(y,r,b)=(200,false,Array.fill(20,20)(false))
lazy val u=new Panel{actor{loop{if(r){b=Array.tabulate(20,20){(i,j)=>def^(i:Int)= -19*(i min 0)+(i max 0)%20
var(c,n,r)=(0,b(i)(j),-1 to 1)
for(x<-r;y<-r;if x!=0||y!=0){if(b(^(i+x))(^(j+y)))c+=1}
focusable=true
preferredSize=new Dimension(y,y)
listenTo(mouse.clicks,keys)
reactions+={case e:MouseClicked=>val(i,j)=(e.point.x/10,e.point.y/10);b(i)(j)= !b(i)(j)case _:KeyTyped=>r= !r}
override def paintComponent(g:Graphics2D){g.clearRect(0,0,y,y);g.setColor(red)
for(x<-0 to 19;y<-0 to 19 if b(x)(y))g.fillRect(x*10,y*10,9,9)}}
def top=new Frame{contents=u}}.main(null)


# Matlab (152)

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
imshow(b)
drawnow
b=p(b,s(b))
end


I dont have Matlab installed right now to test it, I just golfed the code that I wrote a few years ago.
Ungolfed:

%% initialize
Bsize = 20;
nsteps = 100;
board = uint8(rand(Bsize)<0.2); % fill 20% of the board
boardsum = @(im) imfilter(im,[1 1 1; 1 0 1; 1 1 1], 'circular');
step = @(im, sumim) uint8((sumim==3) | (im & (sumim==2)) );

%% run
for i = 1:nsteps
imshow(kron(board,uint8(ones(4))), [])
drawnow
ss(p,i) = sum(board(:));
board = step(board, boardsum(board));
end

• Boardsize is hardcoded but can be anything
• wraps around
• for user input one can change the inital board either by hardcoding another matrix or using the variable editor. Not pretty, but it works
• 20 chars can be saved if the graphical output is skipped, the board will still be printed as text at every iteration. One-pixel cells which change every millisecond are not very useful anyway
• works in R2014a, just tested Oct 6, 2014 at 13:12

# Lua + LÖVE/Love2D, 653 bytes

l=love f=math.floor t={}s=25 w=20 S=1 for i=1,w do t[i]={}for j=1,w do t[i][j]=0 end end e=0 F=function(f)loadstring("for i=1,#t do for j=1,#t[i]do "..f.." end end")()end function l.update(d)if S>0 then return end e=e+d if e>.2 then e=0 F("c=0 for a=-1,1 do for b=-1,1 do if not(a==0 and b==0)then c=c+(t[((i+a-1)%w)+1][((j+b-1)%w)+1]>0 and 1 or 0)end end end g=t[i][j]t[i][j]=(c==3 or(c==2 and g==1))and(g==1 and 5 or-1)or(g==1 and 4 or 0)")F("t[i][j]=t[i][j]%2")end end function l.draw()F("l.graphics.rectangle(t[i][j]==1 and'fill'or'line',i*s,j*s,s,s)")end function l.mousepressed(x,y)S=0 o,p=f(x/s),f(y/s)if t[o]and t[o][p]then t[o][p]=1 S=1 end end


or spaced out:

l=love
f=math.floor
t={}s=25
w=20
S=1
for i=1,w do
t[i]={}
for j=1,w do
t[i][j]=0
end
end
e=0
F=function(f)
loadstring("for i=1,#t do for j=1,#t[i] do  "..f.." end end")()
end
function l.update(d)
if S>0 then
return
end
e=e+d
if e>.2 then
e=0
F([[
c=0
for a=-1,1 do
for b=-1,1 do
if not(a==0 and b==0)then
c=c+(t[((i+a-1)%w)+1][((j+b-1)%w)+1]>0 and 1 or 0)
end
end
end
g=t[i][j]
t[i][j]=(c==3 or(c==2 and g==1))and(g==1 and 5 or-1) or (g==1 and 4 or 0)]])
F("t[i][j]=t[i][j]%2")
end
end
function l.draw()
F("l.graphics.rectangle(t[i][j]==1 and'fill'or'line',i*s,j*s,s,s)") end
function l.mousepressed(x,y)
S=0
o,p=f(x/s),f(y/s)
if t[o]and t[o][p] then
t[o][p]=1
S=1
end
end


Click on the field to add living cells. Click outside of the field to run it.

Try it online!

# brainfuck (715 bytes)

[life.b -- John Horton Conway's Game of Life
(c) 2021 Daniel B. Cristofani
http://brainfuck.org/]

>>>->+++++[>+>++++<<-]+>>[[>>>+<<<-]>+++++>+>>+[<<+>>>>>+<<<-]<-]>>>>[
[>>>+>+<<<<-]+++>>+[<+>>>+>+<<<-]>>[>[[>>>+<<<-]<]<<++>+>>>>>>-]<-
]+++>+>[[-]<+<[>+++++++++++++++++<-]<+]>>[
[+++++++++.-------->>>]+[-<<<]>>>[>>,----------[>]<]<<[
<<<[
>--[<->>+>-<<-]<[[>>>]+>-[+>>+>-]+[<<<]<-]>++>[<+>-]
>[[>>>]+[<<<]>>>-]+[->>>]<-[++>]>[------<]>+++[<<<]>
]<
]>[
-[+>>>-]+>>>>>>[<+<<]>->>[
>[->+>+++>>++[>>>]+++<<<++<<<++[>>>]>>>]<<<[>[>>>]+>>>]
<<<<<<<[<<++<+[-<<<+]->++>>>++>>>++<<<<]<<<+[-<<<+]+>->>->>
]<<+<<+<<<+<<-[+<+<<-]+<+[
->+>[-<-<<[<<<]>[>>[>>>]<<+<[<<<]>-]]
<[<[<[<<<]>+>>[>>>]<<-]<[<<<]]>>>->>>[>>>]+>
]>+[-<<[-]<]-[
[>>>]<[<<[<<<]>>>>>+>[>>>]<-]>>>[>[>>>]<<<<+>[<<<]>>-]>
]<<<<<<[---<-----[-[-[<->>+++<+++++++[-]]]]<+<+]>
]>>
]

[Type e.g. "be" to toggle the fifth cell in the second row, "q" to quit,
or a bare linefeed to advance one generation.]


# Batch 1131 bytes

Golfed version of my answer here

• requires windows 10 with virtual terminal support
• version has been modified to allow for input of pattern if called with custom args for Y and X axis.
@Echo off&Set $=Set &Cls For /f %%e in ('echo prompt$E^|cmd')Do %$%\E=%%e %$%F=For /l %%# in (&Setlocal EnableDelayedExpansion
%$%/AY=20,X=20&If not "%~2"=="" %$%/AY=%1,X=%2,C=1
%F:#=n%0 1 9)Do %F:#=s%0 1 1)Do %$%#%%n%%s=0 %$%/A#21=1,#30=1,#31=1,D=1001001010
%$%t}=&%F:#=y%1 1 %Y%)Do %F:#=x%1 1 %X%)Do For /f %%v in ('%$%/a !random! %%9+1')Do (
%$%/An.%%y;%%x=%%y-1,e.%%y;%%x=%%x+1,s.%%y;%%x=%%y+1,w.%%y;%%x=%%x-1 If %%y==1 %$%n.%%y;%%x=%Y%
If %%y==%Y% %$%s.%%y;%%x=1 If %%x==1 %$%w.%%y;%%x=%X%
If %%x==%X% %$%e.%%y;%%x=1 %$%%%y;%%xN=}!n.%%y;%%x!;%%x+}%%y;!e.%%y;%%x!+}!s.%%y;%%x!;%%x+}%%y;!w.%%y;%%x!+}!n.%%y;%%x!;!e.%%y;%%x!
%$%%%y;%%xN=!%%y;%%xN!+}!n.%%y;%%x!;!w.%%y;%%x!+}!s.%%y;%%x!;!e.%%y;%%x!+}!s.%%y;%%x!;!w.%%y;%%x! If .!c!==. (%$%t}=!t}!}%%y;%%xH!D:~%%v,1!,)Else (<nul %$%/p=%\E%[%%y;%%xH?&Title %%y;%%x 0/1: For /f %%V in ('Choice /N /C:01')Do (%$%q=%%V&%$%t}=!t}!}%%y;%%xH%%V,&<nul %$%/p=%\E%[%%y;%%xH!q!)))
%F% in ()Do (%$%O=!t}:}=%\E%[! Echo(!O:,=!%\E%[?25l %$%/A!t}:H==!1&%$%t}= For /f "tokens=1-2 delims=}=" %%1 in ('%$%}')Do (%$%/A[n]=!%%1N! For %%s in ("![n]!%%2")Do %$%t}=!t}!}%%1H!#%%~s!,))


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