More general [cellular automaton] rules

The programs given so far are for cellular automata with rules of the specific kind described in this chapter. In general, however, a 1D cellular automaton rule can be given as a set of explicit replacements for all possible blocks of cells in each neighborhood (see page 60). Thus, for example, rule 30 can be given as

{{1, 1, 1} -> 0, {1, 1, 0} -> 0, {1, 0, 1} -> 0, {1, 0, 0} -> 1, {0, 1, 1} -> 1, {0, 1, 0} -> 1, {0, 0, 1} -> 1, {0, 0, 0} -> 0}

To use rules in this form, CAStep can be rewritten as

CAStep[rule_, a_List] := Transpose[{RotateRight[a],a,RotateLeft[a]}]/.rule

or

CAStep[rule_, a_List] := Partition[a, 3, 1, 2] /. rule

The rules that are given can now contain patterns, so that rule 90, for example, can be written as

{{1, _, 1} -> 0, {1, _, 0} -> 1, {0, _, 1} -> 1, {0, _, 0} -> 0}

But how can one set up a program that can handle rules in several different forms? A convenient approach is to put a "wrapper" around each rule that specifies what form the rule is in. Then, for example, one can define

CAStep[ElementaryCARule[rule_List], a_List] := rule[[8 - (RotateLeft[a] + 2 (a + 2 RotateRight[a]))]]

CAStep[GeneralCARule[rule_, r_Integer:1], a_List] := Partition[a, 2r+1, 1, r+1] /. rule

CAStep[FunctionCARule[f_, r_Integer:1], a_List] := Map[f, Partition[a, 2r+1, 1, r+1]]

Note that the second two definitions have been generalized to allow rules that involve r neighbors on each side. In each case, the use of Partition could be replaced by Transpose[Table[RotateLeft[a, i], {i, -r, r}]]. For efficiency in early versions of Mathematica, explicit rule lists in the second definition can be preprocessed using Dispatch[rules], and functions in the third definition preprocessed using Compile[{{x,_Integer,1}},body].

I discuss the implementation of totalistic cellular automata on page 886, and of higher-dimensional cellular automata on page 927.