# Game of Life (GoL) in 3D cellular automaton and its rule numbers

I walked through How to calculate CellularAutomaton rule numbers in higher dimensions? to produce the following code for the Advent of Code, day 17, which asks for "Life, but in 3D". More concretely:

• an active cell with exactly 2 or 3 live neighbours in its 27-cell neighbourhood stays active, otherwise dies;
• an inactive cell with exactly 3 live neighbours becomes active, otherwise stays dead.

The code performs one time-step of the automaton, starting with a 2D slice of the space configured as a Life glider, and everything else zero.

 With[{d = 3},
CellularAutomaton[<|
"OuterTotalisticCode" ->
Total[d^(d #[[2]] + #[[1]]) & /@ {{0, 3}, {1, 2}, {1, 3}}],
"Dimension" -> d, "Colors" -> 2,
"Neighborhood" ->
"Moore"|>, {{{{0, 1, 0}, {0, 0, 1}, {1, 1, 1}}}, 0}, {1, All}]]


Running the code, however, it becomes clear that it is total nonsense.

What has this code actually done?

A check for correctness is that after one timestep, we have evolved the initial slice forward by one space in 2D Life, so we should see a glider step in the central slice. What was actually produced is… definitely not that.

You should probably also CHECK HERE "my answer", which explains the enumeration schema for CAs. It is pretty simple for outer totalistic rules. In 2D you can define GoL and test it on a glider:

GoL2D=<|"OuterTotalisticCode"->224,"Dimension"->2,"Neighborhood"->9|>;
ArrayPlot[#,ImageSize->40,Mesh->True]&/@
CellularAutomaton[GoL2D,{{{0,1,0},{0,0,1},{1,1,1}},0},8]


Where is 224 rule number is coming? Well, - from special ordering of outer totalistic rule table. After running

RulePlot@CellularAutomaton[GoL2D]


where arrows show the order of how to read out binary code (black 1, white 0) so you easily get 224 by running:

FromDigits[
{0,0,0,
0,0,0,
0,0,0,
0,1,1,
1,0,0,
0,0,0},2]


224

This is equivalent to

Flatten[Table[{{1,k}->If[k==2||k==3,1,0],{0,k}->If[k==3,1,0]},{k,8,0,-1}],1]
%//Values//FromDigits[#,2]&


{{1,8}->0,{0,8}->0,{1,7}->0,{0,7}->0,{1,6}->0,{0,6}->0,{1,5}->0,{0,5}->0,{1,4}->0,{0,4}->0,{1,3}->1,{0,3}->1,{1,2}->1,{0,2}->0,{1,1}->0,{0,1}->0,{1,0}->0,{0,0}->0}

224

where the 1st number in the Key is value of central cell, and 2nd number is value of sum of outer neighbors. This is easily generalizable to 3D, which gives same rule number:

Flatten[Table[{{1,k}->If[k==2||k==3,1,0],{0,k}->If[k==3,1,0]},{k,26,0,-1}],1]
%//Values//FromDigits[#,2]&


{{1,26}->0,{0,26}->0,{1,25}->0,{0,25}->0,{1,24}->0,{0,24}->0,{1,23}->0,{0,23}->0,{1,22}->0,{0,22}->0,{1,21}->0,{0,21}->0,{1,20}->0,{0,20}->0,{1,19}->0,{0,19}->0,{1,18}->0,{0,18}->0,{1,17}->0,{0,17}->0,{1,16}->0,{0,16}->0,{1,15}->0,{0,15}->0,{1,14}->0,{0,14}->0,{1,13}->0,{0,13}->0,{1,12}->0,{0,12}->0,{1,11}->0,{0,11}->0,{1,10}->0,{0,10}->0,{1,9}->0,{0,9}->0,{1,8}->0,{0,8}->0,{1,7}->0,{0,7}->0,{1,6}->0,{0,6}->0,{1,5}->0,{0,5}->0,{1,4}->0,{0,4}->0,{1,3}->1,{0,3}->1,{1,2}->1,{0,2}->0,{1,1}->0,{0,1}->0,{1,0}->0,{0,0}->0}

224

The rule number is the same in this specific case as generalization to higher dimension adds only zeros on the left into binary code for the rule number. Here this rule's CA starts from random cube 9x9x9 embedded in empty field:

GoL3D=<|"OuterTotalisticCode"->224,"Dimension"->3,"Neighborhood"->27|>;
Image3D[#,ColorFunction->"WhiteBlackOpacity"]&/@
CellularAutomaton[GoL3D,{RandomInteger[1,{3,3,3}],0},7]


Here is a way to test on some simple manual initial conditions by crafting 9x9 cube and seeing how values die according to the right real GoL rules. Here just 3 live cells will make fireworks you see at the top:

ini={Table[0,3,3],{{1,0,0},{0,1,1},{0,0,0}},Table[0,3,3]};
Image3D[ini,ColorFunction->"WhiteBlackOpacity"]

anim=Image3D[#,ColorFunction->"WhiteBlackOpacity"]&/@
CellularAutomaton[GoL3D,{ini,0},30];

Export["anim.gif",anim,AnimationRepetitions->Infinity,ImageSize->400]

• I don't understand why the rule number 224 stayed the same despite the number of dimensions going up by 1. Per mathematica.stackexchange.com/a/202852/30771, the rule number should depend on the dimension. Why has it not done so here? Dec 18, 2020 at 13:39
• @PatrickStevens Because in this specific case higher dimensions just added zeros on the left of binary number, which does not change anything. Here is a toy example: FromDigits[{0,1,1,1,0},2]==FromDigits[{0,0,0,0,0,1,1,1,0},2] gives True. Dec 18, 2020 at 13:50