PythonでL-system

L-systemと呼ばれる、文字置換の再帰で植物とか書ける面白そうなものを見つけたのでpythonで書いてみました。
L-system – Wikipedia
英語版のほうが詳しい

L-system.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*-

"""
Variavles : 置換規則(後述の P )により順次置き換えられてゆく変数の集合。
Constants : 計算が進んでも変化しない定数の集合。
Start : システムの初期状態を示すV の要素からなる文字列。
Rules : V を変化させてゆく置換規則の集合。
"""
def attributesFromDict(d):
        self = d.pop("self")
        for n, v in d.iteritems():
            setattr(self, n, v)

import re
def multiple_replace(text, adict):
    rx = re.compile("|".join(map(re.escape, adict)))
    def one_xlat(match):
        return adict[match.group(0)]
    return rx.sub(one_xlat, text)

class Lsystem():
    def __init__(self, Variavles=None, Constants=None, Start=None, Rules=None):
        attributesFromDict(locals())
        try:
            self.replacementRules = dict(zip([k for k, v in self.Rules], [v for k, v in self.Rules]))
        except TypeError:
            self.replacementRules = None
    def Algae(self):
        return Lsystem(["A", "B"], None, "A", [("A", "AB"), ("B", "A")])
    def Tree(self):
        return Lsystem(["0", "1"], ["[", "]"], "0", [("1", "11"), ("0", "1[0]0")])
    def Fibonacci_number(self):
        return Lsystem(["A", "B"], None, "A", [("A", "B"), ("B", "AB")])
    def Koch(self):
        return Lsystem(["F"], ["+", "-"], "F", [("F", "F+F-F-F+F")])
    def Cantor(self):
        return Lsystem(["A", "B"], None, "A", [("A", "ABA"), ("B", "BBB")])
    def Sierpinski(self):
        return Lsystem(["A", "B"], ["+", "-"], "A", [("A", "B-A-B"), ("B", "A+B+A")])
    def generate(self, n=1, mute=False):
        strings = self.Start
        if not mute:
            print "0:"+strings
            for num, i in enumerate(range(n)):
                strings = multiple_replace(strings, self.replacementRules)
                print str(num+1)+":"+strings
        else:
            for num, i in enumerate(range(n)):
                strings = multiple_replace(strings, self.replacementRules)
        return strings

if __name__ == "__main__":
    import turtle
    turtle.speed(0)

    test = Lsystem().Sierpinski()
    test_out = test.generate(10)
    for s in test_out:
        if s == "A" or s == "B":
            turtle.fd(1)
        elif s == "-":
            turtle.lt(60)
        elif s == "+":
            turtle.rt(60)

エディタに保存して実行すると
スクリーンショット 2013-03-03 21.40.08
こんな感じでシェルピンスキーのギャスケットが描かれる。

広告


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中