《付録》ex_amorphous.py
# -*- coding: utf-8 -*- #=============================================================================== # Copyright (C) 2000-2008, 小泉ひよ子とタマゴ倶楽部 # # Change History: WPF examples # 2008/01/25, IronPython 1.1.1 (download) # 2008/08/22, IronPython 1.1.2 (download) # 2008/03/16, ver.2.0, WPF # 2008/00/00, ver.2.1, IronPython 1.1.2 # Change History: Games # 1988/05, Smalltalk # 2004/09, Java # 2005/02, C# # 2005/03, Jython #=============================================================================== from _ant import * from System.Windows import * from System.Windows.Media import * from System.Windows.Shapes import * from hexOthello import HexStone from organism import * ## -------------------- class ExHexStone: def __init__(self, client, x, y, state, Stroke=None, Fill=None): self.client = client self.name = "_%d_%d"%(x, y) self.shape = self._shape(x, y) if Stroke: self.shape.Stroke = Stroke if Fill: self.shape.Fill = Fill def __repr__(self): return self.name def _shape(self, x, y): name = "_%d_%d"%(x, y) x = HexStone._dx + x * HexStone._width y = HexStone._dy + y * HexStone._height points = PointCollection() for dx, dy in HexStone(x, y, False).vertices: points.Add(Point(x+dx*2, y+dy*2)) s = Polygon( Name=name, HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=Brushes.Black, StrokeThickness=1, Fill=Brushes.Green, Points=points, ) s.MouseUp += self.mouseUp return s def mouseUp(self, sender, e): life = self.client.combineLife(sender.Name) points = PointCollection() for e in life.points: points.Add(e) self.client.addShape(Polygon( HorizontalAlignment=HorizontalAlignment.Center, VerticalAlignment=VerticalAlignment.Center, Stroke=sender.Stroke, StrokeThickness=3, Points=points, )) def points(self): return list(self.shape.Points) ## -------------------- class ExWindow(Window): def __init__(self, Content=None, **args): self.InitializeComponent(Content) self.init() def InitializeComponent(self, Content): self.Content = LoadXaml(Content) def init(self): target = "canvas", self._Controls(target) self.colony = self._colony() def _Controls(self, target): controls = xaml_controls(self) for e in target: setattr(self, e, controls[e]) def _colony(self): colony = Colony() for e in [ ExHexStone(self, 2, 2, False, Stroke=Brushes.Blue, Fill=Brushes.Cyan ), ExHexStone(self, 4, 2, False, Stroke=Brushes.Red, Fill=Brushes.Yellow), ]: self.canvas.Children.Add(e.shape) colony.addCell(e) return colony def combineLife(self, name): return self.colony.detectLife(name).combine() def addShape(self, shape): return self.canvas.Children.Add(shape) ## -------------------- if __name__ == "__main__": xaml = __file__.replace(".py",".xaml") win = ExWindow( Title=__file__, Width=250, Height=150, Content=xaml, ) Application().Run(win) ## --------------------
amorphous:単細胞生命体から多細胞生命体への進化
amorphous を形成する過程で、単細胞生命体から多細胞生命体へと進化したときに、境界線(多角形)を再構築する必要があります。これを、リストの連結によって実現します。
テストケース:単細胞生命体の頂点
環状リストがあると便利ですが、Python の組み込み型 list には、その機能がありません。幸いにも、当面の問題を解決するには、環状リストを2巡するだけで十分です。そこで、組み込み型 list を利用します。
s = "abcdef"
for p in range(6):
print "%d:"%p, circulate(s, p, q=4)
一方の生命体(右赤: abcdef)に着目します。他方の生命体(左青: ABCDEF)と接合した後で、残される頂点を獲得します。頂点 a からのオフセット位置 p(0〜5)を指定したときに、残される4つの頂点(q=4)が得られます。このテストケースを実行すると、
0: bcde 1: cdef 2: defa 3: efab 4: fabc 5: abcd
頂点 a(オフセット位置 p=0)で接合すると、4つの頂点(bcde)が残されるのが分かります。
def circulate(s, p, q):
size = len(s)
start = p+1; stop = p+q+1
if size < stop:
s = s[start:] + s[:stop-size]
else:
s = s[start:stop]
return s
テストケース:多細胞生命体の頂点
2つの生命体が接合した後で形成された、多細胞生命体の頂点を獲得します。
s1 = list("ABCDEF")
s2 = list("abcdef")
for e in range(6):
print "%d:"%e, merge(s1, e, s2, 2)
一方の生命体 s1 に他方の生命体 s2 が接合した後で、形成される多細胞生命体の頂点が得られます。このテストケースを実行すると、
0: ['A', 'f', 'a', 'b', 'c', 'B', 'C', 'D', 'E', 'F'] 1: ['A', 'B', 'a', 'b', 'c', 'd', 'C', 'D', 'E', 'F'] 2: ['A', 'B', 'C', 'b', 'c', 'd', 'e', 'D', 'E', 'F'] 3: ['A', 'B', 'C', 'D', 'c', 'd', 'e', 'f', 'E', 'F'] 4: ['A', 'B', 'C', 'D', 'E', 'd', 'e', 'f', 'a', 'F'] 5: ['A', 'B', 'C', 'D', 'E', 'F', 'e', 'f', 'a', 'b']
頂点 A(オフセット位置 p=0)で接合すると、10個の頂点(AfabcBCDEF)が残されるのが分かります。
def merge(s1, i1, s2, i2): p = (i1+4)%len(s2) q = 6-i2; d = 5-q return s1[:i1+1] + circulate(s2, p, q) + s1[i1+d:]
Python ⇒ IronPython
ここまでのテストケースは、Python でその動作を確認しました。そこで、実際に IronPython を起動して、その動作を確認します。