“Üzgünüm genç adam, ama burası tamamen kaplumbağalar!”


21

Bir Lindenmayer Sistemi Çalıştırın

Bir Lindenmayer Sistemi (veya L sistemi), Thue ve Post sistemleriyle ilgilidir ve botanik modelleme ve fraktal oluşumunda kullanılır .

Bir L sistemi, sembol alfabesinden gelen bir sembolün, bir sembol değiştirme dizisine eşlendiği string-yeniden yazma ile tanımlanmaktadır . Bu haritaların bir koleksiyonu, L sistemini uygun kılar.

Prusinkiewicz tarafından tasarlanan grafiksel çıktı yöntemi, eşleştirmeler , Turtle-Çizim komutları gibi ileri bir geri, sol, sağ, bu tür şeyler gibi belirli sayıda yineleme için bir ilk diziye uygulandıktan sonra ortaya çıkan diziyi yorumlar . Bu, çizimin ölçeğini kontrol etmek için ekstra kod gerektirebilir çünkü farklı yineleme sayıları büyük ölçüde farklı boyutlarda görüntüler üretebilir.

Göreviniz en az sayıda karaktere sahip bir L sistemi yürütmektir. Programınız, uygun giriş (dosya, komut satırı, ancak kaynağın dışında, lütfen) sağlayarak, hem Ejderha Eğrisi hem de Dallanma Saplarını Wikipedia sayfasından yapabilmelidir.

Dallanma Kaynaklanıyor Ejderha Eğrisi

Bu kod golfü.

Düzenleme: İşte size kasabaya gönderdiğim bazı örnekler. SO cevabı / döndür-to-kuzeye { Ben ilk L-sistemi keşfetti } , SO / how-to-programı-a-fraktal cevabı , SO cevap / özyineleme-in-postscript , comp.lang.postscript tartışma resital , postscript l-system koleksiyonu , codegolf.SE/draw-a-sierpinski-triangle {ben ve thomasW arasındaki rekabetin kökeni} .


Sanal alanı atladım. Bu nispeten basit görünüyor ve eğlenceli olmalı.
kullanıcı lüzgarı

BTW, yukarıdaki alıntıların kaynağını bilen var mı? William James'i duydum ve Faraday'ı duydum.
kullanıcı lüzgârı

1
Wikipedia , kaynağın uyuşmazlık içinde olduğunu söylüyor, en iyi ihtimalle Bertrand Russel.
ugoren

ITYM Bertrand Russell .
Paul R,

1
Alfabenin büyüklüğü, kural sayısı, tur sayısı veya olası (görselleştirme) kuralları (düz bir çizgi çizme, bas / pop pozisyonu / açı, kaç derece çevir vb.) Konusunda herhangi bir sınır var mı? o zaman bu ikisini ittirmemiz, patlatmamız, düz çizgiler
çizmemiz

Yanıtlar:


31

Mathematica 200 198 188 171 168

Netlik için eklenen boşluklar:

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)

Nerede:

i: İlk durum;
b: dönüş açısı
h: başlangıç ​​açısı
j: başlangıç ​​konumu
r: üretim kuralları
n: yineleme

Üretim kuralları gramer:

2 = Sola Dön (-);
4 = Sağa Dön (+);
6 = İt ve Sola Dön ("[");
8 = Pop ve Sağa Dön ("]");
C [i] = Çizim (Herhangi bir sembol sayısı)
Başka bir sembol = Hiçbir Şey yapmayın, sadece bir sonraki durumu üretmek için kullanın (Herhangi bir sembol sayısı)

{2,4,6,8} dizisi var çünkü dönüş yapmak için I^n( I= hayali birim) kullanıyorum .

Örnekler:

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

Mathematica grafikleri

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 grafikleri

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 grafikleri

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 grafikleri

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 grafikleri


Sadece modifiye Graphics@ktarafından Graphics@Flatten@kbirçok yinelemeleri kullanmayı planlıyorsanız. Aksi halde, bir Recursion Limit sizi ısırır ve Mma seansınız iptal olur.
Dr. Belisarius

Makro genişletme yöntemim, daha yüksek yinelemelerle benzer bir sorun vardı. İpler çok büyük hale geldi. Ancak buradaki çözüm düzleşmek değildi . :)
luser droog

2
+1 gerçekten çok güzel;) Serin bir gösteri olabilir. Bunları gönderir misiniz?
Vitaliy Kaurov

@VitaliyKaurov Hayır, ancak çabaya değer olduğunu düşünüyorsanız, kullanmaktan çekinmeyin
Dr. belisarius


9

Python, 369 294

Kazanan değil ama yine de denediklerimi postalayacağım.

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'da golf oynamak iyi değil ...... Belki başkası yapabilir.

Giriş

Girdi, "l" adında bir harici dosyadan (uzantı yok), aşağıdaki biçimdedir:
Satır 1 : İlk durum (Aksiyom)
Satır 2 : Virgülle ayrılmış kurallar

Semboller
f ve F: Öne doğru çek
+: 5 derece sağa dön: 5 derece
-sola dön
[: Konumu ve başlığı kaydet
]: Pop konumu ve başlığı
Diğer semboller, çizim fonksiyonu tarafından yoksayılır.

Kurallar
Kural biçimindedir "predecessor":"successor(s)"
Tek veya çift olsun, tırnakların gerekli olduğunu unutmayın.
predecessortek bir karakter olmalı
Ayrıca, örtük sabitler yoktur: Bunlar için açıkça bir değişiklik yok kuralı belirtmelisiniz.

Örnekler

Dallanma kaynaklanıyor

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

Çıktı

Kaynağın bunu çıkarmak için değiştirildiğine dikkat edin. SADECE GÖRÜLEN ALANA GİBİ AŞAĞIDA ÖLÇEKTİR. Konsol, "kaplumbağayı" gizlemek için de kullanılır.

Ejderha eğrisi

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

Çıkış

Yine konsol, "kaplumbağayı" gizlemek için kullanılır.

Sierpinski Üçgeni

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

Çıktı

Jenerasyonları burada 5'e düşürüldü.


3
Sen işlevlerini kaldırarak (Ben 32 karakter olun) iyi bir tasarruf elde edebilirsiniz f, r, l; ove ' a kukla parametre eklemek c; ve sonra sözde anahtarı değiştirerek{'f':fd,'F':fd,'+':rt,'-':lt,'[':o,']':c}[k](5)
Peter Taylor

Ayrıca satır içi yapabilirsiniz gve bence ove csatır içi ififadelerle kaldırmaya değer (beyandan daha ucuz global)
Peter Taylor

@ PeterTaylor iyi iş. Bu işlevlerden bazılarının satırla çizilebileceği konusunda bir fikrim vardı, ancak bunu açıkça ifade etmek için yeterince Python bilmiyordum.
kullanıcı

1
@luserdroog, Python'u da bilmiyorum: Ben sadece neyin işe yaradığını görmek için deneme yaptım ve hata yaptım - yani denediğim bazı şeyler (örneğin , sözde anahtarın içinde ove cdoğrudan lambda kullanarak ) sözdizimi hataları verdi, ancak diğerleri t.
Peter Taylor

Daha fazla golf oynamak için ipuçları: 1. Giriş biçimini değiştirin: Kuralların etrafında parantez isteyin ve aksiyomu kurallardan boşlukla (yeni satır değil) ayırın. Stdin'den 2. Okuma: s,R,*p=input().split(). Son değeri oluşturmak 3. sgöre exec('s="".join(map(eval(R).get,s));'*8). 4. Dışarıda bırakın continue. 5. Yalnızca 1 boşluk girin. 6. ifTestin kenarlarını değiştirerek sonrasındaki boşluğu kaydedin . 7. koyun k:intiçinde dict(ilk girişi) ve sonra gerek yoktur except: try:. (215 karakter alıyorum.)
Monica'yı

7

Javascript (179 bayt)

Kural nesnesi gerçek çizimin tamamını yaptığı için, bunun tam olarak doğru olduğundan emin değil.

Demo (Dragon, animasyonlu):
- Genişletilmiş: http://jsfiddle.net/SVkMR/9/show/light
- Kodlu: http://jsfiddle.net/SVkMR/9/

minified:

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)}

Okunabilir (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)
}

Giriş:

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
};

Kullanımı:

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

Bonus: Altın Sarmal 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
};

Bence animasyon, kurallarla ilgili herhangi bir özgürlüğü telafi etmekten daha fazla. Aferin! +1
maden ocağı

:) Eğlenceli şeyler! .
Shmiddty

5

dipnot 264 298 295 255

İşte farklı yapma girişimim. Genelde kullandığım makro genişlemesinden ziyade, bu özyinelemeyi sınırlamak için yürütme yığınının boyutunu kontrol ediyor. Eğer sınır aşılırsa, prosedürü tekrar tekrar incelemeyi durdurur ve kaplumbağa komutlarını yorumlamaya çalışır (ve pop popaksi takdirde atılır ). Bu yöntemin bir avantajı, büyük miktarda bellek gerektirmemesidir. Bir dezavantaj ise, istifleme kontrolünün oldukça sakar olması, çünkü yığın büyüklüğü bir tekrarlama seviyesinden bir diğerine sadece 1'den fazla büyür.

Düzenleme: Dallanma için +34 karakter.
Düzenleme: -3 karakter. İşlenen yığını kullanmak için özyineleme kontrolü için yeniden tasarlandı. Bu, temel sistemi çok daha basit hale getirir. Fakat parantezlerin bağımsız bir yığına ihtiyacı var, bu yüzden kayıtlı pozisyonu sözlük yığına koydum ve neredeyse tüm birikimleri geri ödedim.

Ayrıca, diziler ve adlar yerine, dizeleri ve tamsayıları kullanmak için yeniden tasarlandı.

Düzenleme: -40 karakter. Sistem adlarını numarasına göre çağırmak için iki yordam eklendi ( Çalışmak için ham ikili belirteçler elde edemiyorum . Ama bu deyim benim için çalışıyor.)

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

Yarı yorumlanmış ikili.

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

Ne yazık "ikili".

[/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-sisteminin diktatördeki bir sözlükte, ilk dizeyle ve kaplanın işlemsel yığındaki başlangıç ​​pozisyonu ile (örneğin kaynağa göre hazırlandığı gs dragon.sys lsys.ps) tanımlanmasını gerektirir.

Ejderha Eğrisi.

%!
[                     %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

Dallanma Kaynaklanıyor.

[
    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

Ungolfed ve yorum yaptı.

[                                 % 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

Çalıştırmak için, bu 3 blok 3 dosya olarak kaydedilebilir: dragon.ps, stems.ps, lsys.ps (yukarıdaki program bloklarından herhangi biri aynı şekilde çalışacaktır). Sonra gs ile çalıştırın: gs dragon.ps lsys.psveya gs stems.ps lsys.ps. Ayrıca istenirse önce birleştirilebilirler: cat dragon.ps lsys.ps | gs -veya cat stems.ps lsys.ps | gs -.

ejderha eğrisi

Resim yok kaynaklanıyor. Daha yüksek derinliklerde daha ilginç hale gelmiyor.


4

Mathematica 290

Bu çıplak kemik uygulaması, işleme yerine üretime odaklanır. Üretim kurallarını kullanmaz. Bu yüzden bu zorluğa uygun bir cevap olmayabilir.

Dallanma, Theo Gray'in gösterisinden uyarlanmıştır .

kod

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

kullanım

İlk parametre Ejderha Eğrisi mi Dal Dallarının mı görüntüleneceğini belirler. İkinci terim nesli ifade eder.

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

ikinci fotoğraf


Daha fazla örnek

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

fractal3


1
Çok güzel. Fakat kuralı tartışmak için bazı baytları kurtarmaz mı?
kullanıcı lüzgârı

Bu genel bir çözüm olsaydı, belki biri parametreden ziyade bir kuralı geçebilirdi. Lindenmayer Systems hakkında şu anda olduğumdan daha fazla bilgili olmalıydım.
DavidC

Ben matematik okumam. Biraz gidip öğrenmeliyim. (yığına ekleyin :) Ancak, "görüntünün tanımını neyin oluşturduğunu, onu yönlendiren motordan farklı olarak" anlamını çıkarabileceğiniz anlamına gelebilir. Görüntünün bir özelliğini kontrol etmek için verileri değiştirebilirseniz , motora düzgün dokunmaktan bağımsız olarak ; Bunun bir L sistemine "işlevsel olarak eşdeğer" olduğunu düşünürdüm. [ Bu size çalışmanız için birçok boşluk bırakmalı;) ]. Yine de +1 'çünkü çok güzel.
luser droog

1
@dude Bence grafik gereksinimleri onlar için uygun değil çünkü
Dr. belisarius

1
Sonunda ağacınız için l-sistemi A->F[+A][-A]F+-[]
çözdüm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.