ライフゲーム(多次元拡張) | Pythonでなんか作ってみる

ライフゲーム(多次元拡張)

前回のライフゲームは2次元限定だが、ライフゲームのロジック自体は1次元や、3次元以上に簡単に拡張できる。
面倒なので表示系の処理は考えないとすると、前回のプログラムから書き換える関数は、positionsのみで良い。
これは、任意の点の周辺(それ自身も含む)の点の集合を返す関数であるから、与えられた点の次元に応じて返す集合を変えればよい。

#1次元ライフゲームバージョン
def positions(point):
for dx in (-1,0,1):
yield (point[0]+dx,)

もちろん、誕生/死滅の閾値が2次元のままだと動かない。
これを1次元、2次元、3次元の場合と作っていけばいいわけだが、まあ一々書けないので再帰的に処理すると次のようになる。

def positions(point,pos=None,axis=0):
"""指定された任意の次元の点から、その周辺(指定された点を含む)を
示す点のタプルを生成するジェネレータ

1次元の点からその周辺領域を生成
>>> list( positions((1,)))
[(0,), (1,), (2,)]

2次元の点からその周辺領域を生成
>>> list( positions((1,1))) #doctest: +NORMALIZE_WHITESPACE
[(0, 0), (0, 1), (0, 2),
(1, 0), (1, 1), (1, 2),
(2, 0), (2, 1), (2, 2)]

3次元の点からその周辺領域を生成
>>> list( positions((1,1,1))) #doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
[(0, 0, 0), (0, 0, 1), (0, 0, 2),
(0, 1, 0), ...,
(1, 1, 1),
..., (2, 1, 2),
(2, 2, 0), (2, 2, 1), (2, 2, 2)]
"""
if not pos:
pos = list(point)
if axis == len(pos):
yield tuple(pos)
else:
for delta in (-1,0,+1):
pos[axis] = point[axis] + delta
for p in positions(point, pos, axis+1):
yield p

関数の次の行から始まっているのはPythonで特徴的なテスト記法であるdoctestです。
最初に受け取った点の座標をリストに変換後、各項に+1,0,-1の演算を施して周辺集合を返す。ジェネレータにしてあります。
ちなみに、3次元までしか確認していないし、2次元以外ではライフゲームの動作も確認していませんが。