“抱歉,年轻人,但是乌龟一直都在降下来!”


21

执行Lindenmayer系统

Lindenmayer系统(或L-系统)是有关图厄邮政系统和在用于植物的建模分形产生

L系统描述为 字符串重写,其中将来自符号字母的符号映射到符号的替换序列。这些映射的集合构成了L系统本身。

由Prusinkiewicz设计的图形输出方法解释了将映射应用于对象之后的结果序列。 初始序列指定次数的迭代,如Turtle-Drawing命令:向前,向后,向左,向右等。这可能需要额外的代码来控制图形的比例,因为不同的迭代次数可能会产生尺寸完全不同的图像。

您的任务是以最少的字符数执行L系统。您的程序必须能够通过提供适当的输入(文件,命令行,但请在源外部)来渲染Wikipedia页面上的Dragon Curve和Branching Stem。

分枝茎 龙曲线

这是代码高尔夫。

编辑:这是我在城镇周围张贴的一些示例。答案SO /旋转到北{ 那里我第一次发现了L系统 }回答SO /如何对程序-A-分回答SO /递归功能于后记comp.lang.postscript讨论/ recital后记l系统集合codegolf.SE / draw -a- sierpinski - triangle {我和thomasW之间竞争的起源}


跳过沙盒。这似乎相对简单,应该很有趣。
luser droog

顺便说一句,有人知道上述报价的由来吗?我听过威廉·詹姆斯(William James)和法拉第(Faraday)。
luser droog 2012

1
维基百科说起源有争议,最好的猜测是伯特兰·罗素。
ugoren

ITYM Bertrand Russell
Paul R

1
字母的大小,规则数,轮数或可能的(可视化)规则是否有限制(绘制直线,推/弹出位置/角度,旋转多少度等)。如果我们只需要绘制这两个那么我们就需要推动和弹出,画直线,并且能够转动45度,在两个方向上,只有两个规则,大小4的字母
shiona

Answers:


31

数学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@kGraphics@Flatten@k,如果你打算使用多次迭代。否则,递归限制将咬住您,您的Mma会话将中止。
belisarius博士13年

我的宏扩展方法在迭代次数较高时也存在类似的问题。弦变得巨大了。但是那里的解决方案并没有解决。:)
luser droog

2
的确+1非常好;)可能很酷。你提交那些吗?
Vitaliy Kaurov

@VitaliyKaurov Nope,但如果您认为值得付出的话,请随时使用
belisarius博士13年


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个字符)frl,向o和添加虚拟参数c; 然后将伪开关更改为{'f':fd,'F':fd,'+':rt,'-':lt,'[':o,']':c}[k](5)
Peter Taylor

您也可以内联g,我认为o并且c值得通过内联if语句(比global声明更便宜)来消除
Peter Taylor

@PeterTaylor很好。我有一个直觉,其中一些函数可以内联,但对Python的了解不足以明确表达它。
luser droog 2013年

1
@luserdroog,我也不知道Python:我只是反复试验才能看到有效的方法-即,我尝试过的某些事情(例如,将lambdas用于伪开关oc直接在伪开关中使用)产生了语法错误,而其他错误则没有。 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字节)

由于规则对象会执行所有实际图形,因此不能完全确定是否符合条件。

演示(Dragon,动画):
-扩展: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

:) 好玩的东西!。
2013年

5

后记 264 298 295 255

这是我尝试做不同的尝试。这不是检查我通常使用的宏扩展,而是检查执行堆栈的大小以限制递归。如果超出界限,它将停止递归检查过程,并尝试解释乌龟命令(pop pop否则放弃)。此方法的优点是它不需要大量的内存。缺点是递归控制相当笨拙,因为从一个递归级别到下一个递归级别,堆栈的大小增长了不止1。

编辑: +34个字符的分支。
编辑: -3个字符。重新设计为使用操作数堆栈进行递归控制。这使基本系统更加简单。但是方括号需要一个独立的堆栈,因此我将保存的位置放在字典堆栈中,几乎还清了所有节省的款项。

此外,重新设计为使用字符串和整数而不是数组和名称。

编辑: -40个字符。添加了两个通过数字调用系统名称的过程(我似乎无法使用原始的二进制令牌。但是这个惯用语对我有用。)

/*{<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

它要求在字典堆栈的字典中定义L系统,并在操作数堆栈上加上乌龟的初始字符串和起始位置(例如,添加到源代码中gs dragon.sys lsys.ps)。

龙曲线。

%!
[                     %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个块可以另存为3个文件:dragon.ps,stems.ps,lsys.ps(以上任何程序块都可以相同地工作)。然后使用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]]]]

用法

第一个参数确定将显示“ Dragon Curve”还是“ Branch Stems”。第二个术语指代。

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

第二张照片


更多例子

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

分形3


1
很漂亮。但是它不保存一些字节以将规则作为参数传递吗?
luser droog 2012

如果这是一种通用解决方案,则可能可以传递规则而不是参数。我必须比现在更加了解Lindenmayer Systems。
DavidC 2012

我不读mathematica。我应该去学一些。(将其添加到堆栈中:)但是您可以将其解释为意味着“构成图像描述的任何内容,都不同于驱动图像的引擎”。然后,您可以修改数据以控制图像的某些功能,而不必触摸引擎本身;我认为这在功能上等同于L系统。[ 这应该给您带来很多漏洞;) ]。无论如何+1是因为它是如此的漂亮。
luser droog 2013年

1
@dude我认为是因为图形要求不适用于他们
belisarius博士2013年

1
最终弄清楚了树的l系统:A->F[+A][-A]在哪里F移动,+向左-旋转30,向右旋转30和[/ ]是push / pop
Shmiddty 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.