「申し訳ありませんが、若い男性ですが、それはずっと亀です!」


21

Lindenmayerシステムを実行する

A Lindenmayerシステム(またはL-システム)に関連しThue及びポストシステムとで使用されている植物モデリング及びフラクタル世代

Lシステムは、シンボルアルファベットからのシンボルがシンボルの置換シーケンスにマッピングされる文字列書き換えによって記述されます。これらのマッピングのコレクションは、適切なLシステムを構成します。

Prusinkiewiczによって考案されたグラフィカルな出力方法は、タートル描画コマンドとして、指定された反復回数のマッピングが初期シーケンスに適用された後、結果のシーケンスを解釈します:前方、後方、左、右、など。反復回数が異なるとサイズが大幅に異なる画像が生成される可能性があるため、これには図面のスケールを制御するための追加コードが必要になる場合があります。

あなたの仕事は、最小数の文字でLシステムを実行することです。プログラムは、適切な入力(ファイル、コマンドライン、ソースの外部をお願いします)を提供することにより、ウィキペディアのページからドラゴンカーブと分岐ステムの両方をレンダリングできる必要があります。

分岐ステム ドラゴンカーブ

これはコードゴルフです。

編集:これは私が町の周りに投稿したいくつかの例です。SO / rotate-to-northへの回答{ 私が最初にLシステムを発見した場所 }SO / how-to-program-a-fractalへの回答、SO / recursion-in-postscriptへの回答comp.lang.postscriptディスカッション/リサイタル追記L-システム収集codegolf.SE/draw-a-sierpinski-triangle {自分とthomasW間の競争の起源}


サンドボックスをスキップしました。これは比較的簡単に思え、楽しいはずです。
luser droog

ところで、誰も上記の引用の起源を知っていますか?私はウィリアム・ジェームスを聞いた、そしてファラデーを聞いた。
luser droog

1
ウィキペディアは、起源は論争にあると言っています、最も良い推測はバートランド・ラッセルです。
ウゴレン

ITYMバートランドラッセル
ポールR

1
アルファベットのサイズ、ルールの数、ラウンドの数、または可能な(視覚化)ルール(直線を描く、プッシュ/ポップの位置/角度、回転数など)に制限はありますかこれら2つは、押して飛び出し、直線を描き、両方向に45度回転できる必要があります。2つのルールとサイズ4のアルファベットだけです。
shiona12年

回答:


31

Mathematicaの200 198 188 171 168

明確にするために追加されたスペース:

f[i_, b_, h_, j_, r_, n_] :=
 (a = h; p = j; s = k = {}; t = Flatten;
  (Switch[#,
      6, s = {a, p, s},
      8, {a, p, s} = s,
      _C, k = {k, Line@{p, p += {Cos@a, Sin@a}}}];
     If[# < 9, a += I^# b ]) & /@ t@Nest[# /. r &, i, n];
  Graphics@t@k)

どこで:

i:初期状態。
b:回転角
h:初期角
j:初期位置
r:生産規則
n:繰り返し

生産規則の文法:

2 =左折(-);
4 =右折(+);
6 =左に押して回す( "[");
8 =ポップして右折( "]");
C [i] =描画(任意の数のシンボル)
他の任意のシンボル=何もしない、次の状態の生成に使用する(任意の数のシンボル)

{2,4,6,8}シーケンスは、I^nI=虚数単位)を使用してターンしているためにあります。

例:

f[{C[1], X}, Pi/2, 0, {0, 0}, {X -> {X, 4, Y, C[1]}, Y -> {C[1], X, 2, Y}}, 10]

Mathematicaグラフィックス

f[{C@1}, Pi/2, 0, {0,0}, {C@1->{C@1, 2, C@1, 4, C@1, 4, C@1, 2, C@1}}, 6]

Mathematicaグラフィックス

f[{C[1]}, Pi/4, Pi/2, {0, 0}, {C[2] -> {C[2], C[2]}, C[1] -> {C[2], 6, C[1], 8, C[1]}}, 10]

Mathematicaグラフィックス

f[{C[1]}, Pi/3, 0, {0, 0}, {C@1 -> {C@2, 4, C@1, 4, C@2}, C@2 -> {C@1, 2, C@2, 2, C@1}}, 10]

Mathematicaグラフィックス

f[{X},5/36 Pi, Pi/3, {0,0},{X->{C@1, 4, 6, 6, X, 8, 2, X, 8, 2, C@1, 6, 2, C@1, X, 8, 4, X},
                            C@1->{C@1, C@1}}, 6]

Mathematicaグラフィックス


多くの反復を使用Graphics@kするGraphics@Flatten@k場合は、変更するだけです。そうしないと、再帰制限が噛みつき、Mmaセッションが中止されます。
ベリサリウス博士13年

私のマクロ展開方法には、反復回数が増えると同様の問題がありました。文字列は巨大になります。しかし、そこでの解決策は平坦化することではありませんでした。:)
luser droog

2
+1確かに素晴らしい;)クールなデモンストレーションになる可能性があります。それらを提出しますか?
ビタリーカウロフ

@VitaliyKaurovいや、しかし、あなたはそれの価値がある努力と思えばそれを使用して自由に感じる
博士ベリサリウス


9

パイソン、369 294

勝者ではありませんが、とにかく試したことを投稿します。

from turtle import*
I=open('l').read().split()
s,S,p=I[0],'',[]
for j in range(8):
    for i in s:S+=eval('{'+I[1]+'}')[i]
    s,S=S,''
for k in s:
    if k=='[':p+=[heading(),pos()];continue
    if k==']':pu();goto(p.pop());seth(p.pop());pd();continue
    try:{'f':fd,'F':fd,'+':rt,'-':lt}[k](5)
    except:pass

Pythonのゴルフが苦手......他の誰かができるかもしれません。

入力

入力は、「l」(拡張子なし)という名前の外部ファイルからのもので、次の形式を使用します
。1行目:初期状態(公理)
2行目:コンマ区切りルール

記号
fF:前に引く
+:右に5度回転する
-:左に5度回転する
[:位置と見出しを保存する
]:ポップの位置と見出し
に引く他の記号は描画機能によって無視されます。

ルールルール
の形式は、"predecessor":"successor(s)"
シングルまたはダブルにかかわらず、引用符が必要であることに注意してください。
predecessor単一の文字でなければなりません。
また、暗黙の定数はありません。これらには、変更しないルールを明示的に指定する必要があります。

分岐ステム

------------------f
'-':'-','+':'+','[':'[',']':']','F':'FF','f':'F[+++++++++f]---------f'

出力

グラフを可視領域にスケールダウンするためにのみ、これを取得するためにソースが変更されることに注意してください。コンソールは、「カメ」を隠すためにも使用されます。

ドラゴンカーブ

fx
'-':'-','+':'+','[':'[',']':']','f':'f','x':'x++++++++++++++++++yf','y':'fx------------------y'

出力

再び、コンソールは「カメ」を隠すために使用されます。

シェルピンスキートライアングル

f------------------------F------------------------F
'-':'-','+':'+','[':'[',']':']','f':'f------------------------F++++++++++++++++++++++++f++++++++++++++++++++++++F------------------------f','F':'FF'

出力

世代はここでは5に減りました。


3
あなたは機能を除去することにより、(私はそれ32文字にする)まともな節約を得ることができfrloおよびにダミーパラメータを追加しますc。その後、擬似スイッチを{'f':fd,'F':fd,'+':rt,'-':lt,'[':o,']':c}[k](5)
Peter Taylor

また、インラインすることができg、と私は考えるoc価値がインラインで排除されているif(より安い文global宣言)
ピーター・テイラー

@PeterTaylorお疲れ様でした。これらの関数のいくつかはインライン化できるという直感がありましたが、明確にそれを示唆するのに十分なPythonを知りませんでした。
luser droog

1
@luserdroog、私は、Pythonを知らないのいずれか:私は働いていたものを見るために試行錯誤をした-つまりは、私が試したことのいくつかを(例えばラムダを使用するoc、直接擬似スイッチで)構文エラーを与えたが、他はdidnの」 t。
ピーターテイラー

さらにゴルフをするためのヒント:1.入力形式を変更する:規則の周りにブレースを必要とし、公理と規則をスペース(改行ではなく)で分けます。2. stdinから読み取りますs,R,*p=input().split()。3. sby の最終値を生成しexec('s="".join(map(eval(R).get,s));'*8)ます。4.除外しcontinueます。5. 1スペースだけインデントします。6. ifテストの側面を切り替えて、スペースを節約します。7.入れk:intdict(最初のエントリ)、その後、あなたは必要ありませんexcept: try:。(私は215文字を取得します。)
モニカを

7

Javascript(179バイト)

ルールオブジェクトが実際の描画をすべて行うため、これが適切かどうかは完全にはわかりません。

デモ(ドラゴン、アニメーション):
-展開:http
: //jsfiddle.net/SVkMR/9/show/light-コードあり:http : //jsfiddle.net/SVkMR/9/

縮小:

function L(c,r,n){o=(function g(d,s,o,i){for(o=i='';a=d&&s[i++];)o+=r.r[a]?g(d-1,r.r[a]):a;return o||s;})(n,r.r[r.s]);(function z(i){r[s=o[i]]&&r[s](c)||setTimeout(z,10,i+1)})(0)}

読み取り可能(ish):

function L(c,r,n){
    o=(function g(d,s,o,i){
        for(o=i='';a=d&&s[i++];)o+=r.r[a]?g(d-1,r.r[a]):o+=a
        return o||s
    })(n,r.r[r.s]);

    (function p(i){
        r[s=o[i]]&&r[s](c)||setTimeout(p,10,i+1)
    })(0)
}

入力:

var sierspinski = {
    r:{'A':'B-A-B','B':'A+B+A'},
    '+':function(c){c.rotate(-this.a);c.rotate(this.a-=Math.PI/3)},
    '-':function(c){c.rotate(-this.a);c.rotate(this.a+=Math.PI/3)},
    'A':function(c){c.beginPath();c.moveTo(0,0);c.translate(this.m,0);c.lineTo(0,0);c.stroke()},
    'B':function(c){this['A'](c)},
    s:'A',
    a:0,
    m:1
};

var koch = {
    r: {'F':'F+F-F-F+F'},
    '+':function(c){c.rotate(-this.a);c.rotate(this.a-=Math.PI/2)},
    '-':function(c){c.rotate(-this.a);c.rotate(this.a+=Math.PI/2)},
    'F':function(c){c.beginPath();c.moveTo(0,0);c.translate(this.m,0);c.lineTo(0,0);c.stroke()},
    s:'F',
    a:0,
    m:2
};
var dragon = {
    r: {'X':'X+YF','Y':'FX-Y'},
    '+':function(c){c.rotate(-this.a);c.rotate(this.a-=Math.PI/2)},
    '-':function(c){c.rotate(-this.a);c.rotate(this.a+=Math.PI/2)},
    'F':function(c){c.beginPath();c.moveTo(0,0);c.translate(this.m,0);c.lineTo(0,0);c.stroke()},
    s:'X',
    a:0,
    m:5
};

var algae = {
    r: {'A':'B[A]A','B':'BB'},
    '[':function(c){c.save();c.rotate(Math.PI/4);},  // save/restore will push/pop current state of context. 
    ']':function(c){c.restore();c.rotate(-Math.PI/4);},
    'A':function(c){c.beginPath();c.moveTo(0,0);c.translate(this.m,0);c.lineTo(0,0);c.stroke()},
    'B':function(c){this['A'](c);},
    s:'A',
    a:-Math.PI/2,
    m:1
};

var tree = {
    r:{'X':'F-[[X]+X]+F[+FX]-X','F':'FF'},
    '+':function(c){c.rotate(-this.a);c.rotate(this.a+=Math.PI/180*25)},
    '-':function(c){c.rotate(-this.a);c.rotate(this.a-=Math.PI/180*25)},
    '[':function(c){c.save();},
    ']':function(c){c.restore();},
    'F':function(c){c.beginPath();c.moveTo(0,0);c.translate(this.m,0);c.lineTo(0,0);c.stroke()},
    s:'X',
    a:-Math.PI/180*25,
    m:5
};

使用法:

var ctx = document.getElementById('l').getContext('2d'); // grab context
ctx.translate(299.5,199.5); // start drawing from center, fractional pixels because the canvas draws lines centered on the x/y coord specified
L(ctx, dragon, 8); // pass in context, rules object, and recursion cap

ボーナス:ゴールデンスパイラル http://jsfiddle.net/SVkMR/35/show/light/

var golden = {
    r:{'A':'FT[TT]A','T':'+F'},
    'F':function(c){c.beginPath();c.moveTo(0,0);c.translate(this.m,0);c.lineTo(0,0);c.stroke()},
    '[':function(c){c.save();},
    ']':function(c){
        c.restore();

        c.beginPath();
        c.arc(0,-this.m,this.m,Math.PI/2,Math.PI);
        c.stroke();

        this.m+=this.d;this.d=this.m-this.d
    },
    '+':function(c){c.rotate(-Math.PI/2);},
    s:'A',
    a:-Math.PI/2,
    m:1,
    d:0
};

アニメーションは、ルールの自由を補う以上のものだと思います。よくやった!+1
luser droog

:)楽しいもの!。
-Shmiddty

5

追記 264 298 295 255

これを違うやり方でしようとする私の試みがあります。私が通常使用するマクロ展開ではなく、これは実行スタックのサイズをチェックして再帰を制限します。境界を超えると、プロシージャの再帰的な検査を停止し、タートルコマンドの解釈を試みます(pop popそうでない場合は破棄します)。この方法の利点は、大量のメモリを必要としないことです。不利な点は、再帰サイズが1つの再帰レベルから次のレベルに1を超えて大きくなるため、再帰制御がかなり不器用であることです。

編集:分岐用に+34文字。
編集: -3文字。再帰制御にオペランドスタックを使用するように再設計されました。これにより、基本システムがはるかに単純になります。しかし、ブラケットには独立したスタックが必要なので、保存した位置を辞書スタックに配置し、すべての節約分をほぼ払い戻しました。

また、配列と名前の代わりに文字列と整数を使用するように再設計されました。

編集: -40文字。システム名を番号で呼び出すための2つの手順を追加しました(生のように思えないバイナリトークンを機能。しかし、このイディオムは機能します)。

/*{<920>dup 1 4 3 roll put cvx exec}def/${//* 73
*}def[/T[48{}49{}43{A<88>$}45{A<6e88>$}70{R
0<85>$}91{<1e39>$[/.[<286827>$]cvx>><0d0d>$}93{.<9c6b1e39390d>$}>>/S{dup
B eq{T<0d3e>${<643f>$}<4939>$}{exch{<643e>$ 1 add S}73 *}85 * 1 sub}>><0d6b>$
0 S<a7>$

セミコメントバイナリ。

/*{<920>dup 1 4 3 roll put cvx exec}def/${//* 73 *}def %73=forall
[/T[70{R 0<85>$}48{}49{} %<85>=rlineto
43{A<88>$}45{A<6e88>$} %<88>=rotate <6e>=neg
91{<1e39>$ %<1e>=currentdict <39>=end
    [/.[<286827>$]cvx>> %<28>=currentpoint <68>=matrix <27>=currentmatrix
        <0d0d>$} %<0d>=begin
93{.<9c6b1e39390d>$}>> %<9c>=setmatrix <6b>=moveto
/S{dup B eq{T<0d3e>${<643f>$}<4939>$} %<3e>=exch <64>=load <3f>=exec <49>=forall
{exch{<643e>$ 1 add S}73 *}85 * 1 sub}>>
<0d6b>$ 0 S<a7>$  % 85=ifelse <a7>=stroke

非「バイナリ」。

[/T[70{R 0 rlineto}48{}49{}43{A rotate}45{A neg rotate}91{currentdict
end[/.[currentpoint matrix currentmatrix]cvx>>begin begin}93{. setmatrix
moveto currentdict end end begin}>>/S{dup B eq{T begin exch{load exec}forall
end}{exch{load exch 1 add S}forall}ifelse 1 sub }>>begin moveto 0 S stroke

最初の文字列とオペランドスタック上のタートルの開始位置(ソースに追加されるなどgs dragon.sys lsys.ps)を使用して、dictstackの辞書でLシステムを定義する必要があります。

ドラゴンカーブ。

%!
[                     %begin dictionary construction
    % productions are described by integer-key/string-value pairs
    48(0+1F) %0       %ascii code for '0' defined as the string "0+1F"
    49(F0-1) %1       %  "     "   "  '1'   "     "   "    "    "F0-1"
    43(+) %+          %  "     "   "  '+' defined as itself
    45(-) %-          %  "     "   "  '-'   "     "   "
    70(F) %F          %  "     "   "  'F'   "     "   "
    % parameters
    /A 90 %angle
    /R 2  %radius
    /B 10 %maximum recursion-level
>>begin  % L-system dictionary on top of dictstack
(F0)     % initial string on stack
300 400  % starting position on stack

分岐ステム。

[
    48(F[+0]-0) %0
    49(F0-1) %1
    43(+) %+
    45(-) %-
    70(FF) %F
    91([) %[
    93(]) %]
    /A 45 %angle
    /R 5  %radius
    /B 3 %recursion
>>begin
(++0)     % initial string
300 400  % starting position

ゴルフをしていないとコメント。

[                                 % begin dictionary construction
    /T[                           % /T is the Turtle dictionary containing
                                  % integer-key/procedure-value pairs
                                  % keyed to ascii values
        70{R 0 rlineto}        %F  
        48{}                   %0
        49{}                   %1  
        43{A rotate}           %+  
        45{A neg rotate}       %-  

          % For brackets, create a dictionary containing a single procedure '.' (dot)
          % which holds a saved matrix (orientation+size) and currentpoint.
          % Since this procedure is called while the Turtle dict is on top of the
          % dictstack, the temporary dictionary is placed just under the top.
        91{currentdict end[/.[currentpoint matrix currentmatrix]cvx>>begin begin} %[
          % Right bracket: reset position and orientation,
          % pop the dict just under the top.
        93{. setmatrix moveto currentdict end end begin}    %]  
    >>  
    /S{ % stack contains: string recursion-level
        dup B eq{ % hit recursion bound, interpret string as turtle commands
            T begin
                exch % level string
                %dup =
                {                      % iterate through string
                    load exec          % execute turtle command by integer code
                } forall % level       % string has been consumed
            end
            %(B)= pstack
        }{ % recurse
            %(A)= pstack
            exch % level string
            { % level char                   iterate through string
                load exch % string level   process production:load string by int code
                1 add S   % string level+1   increase level and call self
            } forall                       % string has been consumed
        }ifelse
        1 sub            % return level-1
        %(C)= pstack
    }
>>begin
moveto 0 S stroke

これを実行するには、これらの3つのブロックをdragon.ps、stems.ps、lsys.psの3つのファイルとして保存できます(上記のプログラムブロックのいずれも同様に機能します)。次に、gs:gs dragon.ps lsys.psまたはで実行しgs stems.ps lsys.psます。必要に応じて、最初に連結することもできます:cat dragon.ps lsys.ps | gs -またはcat stems.ps lsys.ps | gs -

ドラゴンカーブ

茎の写真はありません。より高い深度では、これ以上面白くなりません。


4

Mathematica 290

この必要最低限​​の実装は、処理ではなく出力に焦点を当てています。プロダクションルールは使用しません。そのため、チャレンジに対する適切な対応ではない可能性があります。

Theo Grayのデモンストレーションから採用された分岐ステム。

コード

f@{a_, b_} := {{a, #}, {b, #}} &[a + (b - a)/2 + {{0, 1/2}, {-1/2, 0}}.(b - a)]; w = Flatten;
h[s_, g_] :=Graphics[If[s == 0,Line /@ Nest[w[f /@ #, 1] &, {{{0, 0}, {1, 0}}}, g], 
 MapIndexed[Line@# &, NestList[w[Map[{{#[[2]], #[[2]] + m.(#[[2]] - #[[1]])}, {#[[2]], 
 #[[2]] + ({{1, -1}, {-1,1}} m).(#[[2]] - #[[1]])}} &, #], 1] &, {{{0, -1}, {0, 0}}}, g]]]]

使用法

最初のパラメーターは、ドラゴンカーブとブランチステムのどちらを表示するかを決定します。2番目の用語は世代を指します。

h[0, 5]
h[1, 5]

2枚目の写真


その他の例

GraphicsGrid@Partition[Flatten[Table[h[j, k], {j, 0, 1}, {k, 10}]], 5]

フラクタル3


1
非常にきれい。しかし、ルールを引数として渡すためにいくつかのバイトを節約しませんか?
luser droog

これが一般的なソリューションである場合、おそらくパラメーターではなくルールを渡すことができます。現在よりも、Lindenmayer Systemsについての知識が必要です。
DavidC

私は数学を読みません。私はいくつかを学びに行く必要があります。(スタックに追加:)しかし、「イメージの説明を構成するものは何でも、それを駆動するエンジンとは異なるもの」を意味するものと解釈することができます。その後、適切なエンジンに触れることとは別に、データを変更して画像の機能を制御できる場合。これは、Lシステムと「機能的に同等」であると考えます。[ それはあなたに働くための抜け穴をたくさん与えるはずです;) ]。とにかく「とてもきれいだから+1」。
luserはドローグ

1
@dudeグラフィック要件がそれらに十分に適していないためだと思う
博士belisarius

1
最後に、ツリーのl-systemをA->F[+A][-A]F+-[]
見つけ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.