"죄송합니다, 청년이지만 거북은 끝까지 내려 왔습니다!"


21

Lindenmayer 시스템 실행

Lindenmayer에 시스템 (또는 L-시스템)에 관한 것이다 Thue포스트 시스템,에서 사용되는 식물 모델링프랙탈 생성 .

L- 시스템은 심볼-알파벳으로부터의 심볼이 대체 심볼 시퀀스로 매핑 되는 문자열 재 작성에 의해 기술된다 . 이러한 매핑 모음은 L 시스템을 적절하게 구성합니다.

Prusinkiewicz가 고안 한 그래픽 출력 방법은 매핑이 지정된 반복 횟수에 대한 초기 시퀀스에 Turtle-Drawing 명령 (앞으로, 뒤로, 왼쪽, 오른쪽, 그런 종류의 물건) 으로 적용된 후 결과 시퀀스를 해석합니다 . 반복 횟수가 다르면 크기가 다른 이미지가 생성 될 수 있으므로 드로잉의 배율을 제어하기 위해 추가 코드가 필요할 수 있습니다.

당신의 임무는 가장 적은 수의 문자로 L 시스템을 실행하는 것입니다. 프로그램은 위키피디아 페이지에서 적절한 입력 (파일, 명령 줄, 소스 외부)을 제공하여 드래곤 커브와 분기 줄기를 모두 렌더링 할 수 있어야합니다.

분기 줄기 드래곤 커브

이것은 코드 골프입니다.

편집 : 다음은 마을 주변에 게시 한 예입니다. SO / rotate-to-north {{ L 시스템을 처음 발견 한 곳 } , SO / how-to-program-a-fractal , SO / re- post -postscript , comp.lang.postscript 토론에 대한 답변 / recital , postscript l-system collection , codegolf.SE/draw-a-sierpinski-triangle {나 자신과 thomasW 사이의 경쟁의 시작} .


샌드 박스를 건너 뛰었습니다. 이것은 비교적 간단 해 보이며 재미 있어야합니다.
luser droog

BTW, 위의 인용의 기원을 아는 사람이 있습니까? 나는 윌리엄 제임스를 듣고 패러데이를 들었습니다.
luser droog

1
Wikipedia에 따르면 그 기원은 논쟁의 여지가 있다고합니다. Bertrand Russel이 가장 좋은 추측입니다.
ugoren

ITYM 버트 랜드 러셀 .
Paul R

1
알파벳의 크기, 규칙 수, 라운드 수 또는 가능한 (시각화) 규칙에 제한이 있습니까? (직선 그리기, 푸시 / 팝 위치 / 각도, 몇도 회전 등) 이 두 개를 누르면 밀고 터지고, 직선을 그리며 두 방향으로 45도 회전 할 수 있으며 두 개의 규칙과 크기 4의 알파벳 만 가능합니다.
shiona

답변:


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^n( I= 허수 단위)를 사용하여 회전하기 때문에 존재합니다.

예 :

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 세션이 중단됩니다.
Dr. belisarius

내 매크로 확장 방법은 반복 횟수가 높을 때 비슷한 문제가있었습니다. 현은 방대하게됩니다. 그러나 해결책은 평평 하지 않았습니다 . :)
luser droog

2
+1 참으로 멋지다;) 멋진 시연이 될 수있다. 제출 하시겠습니까?
Vitaliy Kaurov

@VitaliyKaurov Nope, 그러나 노력할만한 가치가 있다고 생각되면 자유롭게 사용하십시오
Dr. belisarius


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

파이썬을 골프에 능숙하지 않습니다 ... 다른 누군가가 그것을 할 수 있습니다.

입력

입력은 "l"(확장자 없음)이라는 외부 파일에서 다음 형식으로 입력됩니다.
Line 1 : 초기 상태 (Axiom)
Line 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 개 문자 만들기) 괜찮은 절감을 얻을 수 있습니다 f, r, l, o및에 더미 파라미터를 추가하는 단계 c; 그런 다음 의사 스위치를 다음과 같이 변경하십시오{'f':fd,'F':fd,'+':rt,'-':lt,'[':o,']':c}[k](5)
Peter Taylor

또한 인라인 수 g, 나는 생각 oc가치가 인라인으로 제거된다 if합니다 (보다 저렴 문 global선언)
피터 테일러

@PeterTaylor 잘 했어. 나는 그 함수 중 일부가 인라인 될 수 있다는 직관을 가지고 있었지만, 그것을 명확하게 제안하기에 충분한 파이썬을 알지 못했습니다.
luser droog

1
@luserdroog, 내가 파이썬을 모른다 중 하나를 그냥 일을 확인하려면 시행 착오를했다 - 즉, 내가하려고하는 일의 일부를 (예를 들어 람다를 사용 o하고 c직접 의사 스위치) 구문 오류를했다, 그러나 다른 사람 didn를 ' 티.
피터 테일러

추가 골프를위한 힌트 : 1. 입력 형식 변경 : 규칙 주위에 중괄호가 필요하고 규칙 (공백 줄이 아님)으로 규칙과 공리를 분리하십시오. stdin에서 읽습니다 s,R,*p=input().split(). sby 의 최종 값을 생성합니다 exec('s="".join(map(eval(R).get,s));'*8). 4. 나가십시오 continue. 5. 한 칸만 들여 쓰기하십시오. 6. if테스트를 위해 측면을 전환 하여 공간을 절약하십시오 . 7. 넣어 k:int에서 dict(첫 번째 항목)과는 당신은 필요가 없습니다 except: try:. (215 문자를 얻습니다.)
복원 Monica Monica

7

자바 스크립트 (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 이상 증가함에 따라 재귀 제어가 다소 어색하다는 것입니다.

편집 : 분기를 위해 +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 시스템은 dictstack의 사전에 피연산자 스택에서 초기 문자열과 거북이의 시작 위치 (예 : 소스 앞에 추가됨)를 사전에 정의해야합니다 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

이를 실행하기 위해 dragon.ps, stems.ps, lsys.ps의 3 가지 파일을 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

매스 매 티카 290

이 기본 구현은 처리가 아니라 출력에 중점을 둡니다. 프로덕션 규칙을 사용하지 않습니다. 따라서 도전에 대한 적절한 대응이 아닐 수도 있습니다.

분기 줄기는 Theo Grey의 시연 에서 수정되었습니다 .

암호

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]]]]

용법

첫 번째 매개 변수는 용 곡선 또는 분기 줄기를 표시할지 여부를 결정합니다. 두 번째 용어는 세대를 나타냅니다.

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

두 번째 사진


더 많은 예

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

fractal3


1
아주 예뻐요 그러나 규칙을 인수로 전달하기 위해 바이트를 절약하지 않습니까?
luser droog

이것이 일반적인 해결책이라면 아마도 매개 변수가 아닌 규칙을 통과 할 수 있습니다. 나는 현재보다 Lindenmayer Systems에 대해 더 잘 알고 있어야합니다.
DavidC

나는 수학을 읽지 않습니다. 가서 배워야 겠어 (스택에 추가 :) 그러나 "이미지를 설명하는 엔진과는 달리 이미지의 설명을 구성하는 것이 무엇이든"을 의미한다는 것은 해석 할 수 있습니다. 그런 다음 엔진을 만지지 않고 독립적으로 이미지의 일부 기능을 제어하도록 데이터를 수정할 수 있습니다 . 나는 L- 시스템과 "기능적으로 동등"하다고 생각합니다. [ 이것은 당신에게 많은 허점을 제공해야한다;) ]. 어쨌든 +1이기 때문에 +1입니다.
luser droog

1
@dude 나는 그래픽 요구 사항이 그들에게 적합하지 않기 때문이라고 생각합니다
Dr. belisarius

1
마지막으로 당신의 나무를위한 l- 시스템을 알아 냈습니다 : A->F[+A][-A]어디로 F이동하고, +왼쪽으로 30 번 -회전하고, 오른쪽으로 30 번 회전하고 [/ 누르고 / ]누릅니다
Shmiddty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.