Ich mag pythagoreische Bäume

17

... das ist also eine Herausforderung, mich zu einem Baum zu machen.

Erstellen Sie ein Programm oder eine Funktion namens tree, die ein einzelnes ganzzahliges Argument N verwendet und einen Pythagoras-Baum mit einer Tiefe von N Ebenen zeichnet, wobei die Ebene 0 nur der Stamm ist.

Jeder Knotenpunkt des Baumes sollte den Scheitelpunkt des Dreiecks an einem zufälligen Punkt am Umfang platzieren (dieser Punkt sollte gleichmäßig über mindestens 5 gleichmäßig verteilte Punkte oder gleichmäßig über den gesamten Halbkreis verteilt sein).

Optional kann Ihr Baum 3d sein, bunt sein oder je nach Tageszeit beleuchtet werden. Dies ist jedoch Code-Golf, so dass die kleinste Datei gewinnt.

EDIT: Ich schließe den Wettbewerb und akzeptiere die kleinste Antwort, wenn es eine Woche alt ist

Alexander-Brett
quelle
Scheint
DavidC
Falsch. Ich bin nach einem anderen Algorithmus :)
Alexander-Brett
In Ordnung. Meinetwegen. Vielleicht möchten Sie Ihren Beitrag zu "Pythagorean Tree" mit einem neuen Titel versehen.
DavidC
Ich mag Züge? :)
Tomsmeding

Antworten:

15

Mathematica, 246 234 221 Zeichen

g[n_,s_:1]:={p=RandomReal[q=Pi/2],r=##~Rotate~(o={0,0})&,t=Translate}~With~If[n<0,{},Join[#~t~{0,s}&/@(#~r~p&)/@g[n-1,s*Cos@p],t[#,s{Cos@p^2,1+Sin[2p]/2}]&/@(r[#,p-q]&)/@g[n-1,s*Sin@p],{Rectangle[o,o+s]}]]
f=Graphics@g@#&

Dies ist sicherlich nicht der eleganteste / kürzeste Weg, dies zu tun.

Verwendung: f[8]

Bildbeschreibung hier eingeben

Und hier sind beispielsweise Ausgaben für f[6]und f[10]jeweils.

Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben

Etwas ungolfed:

g[n_, s_:1] := With[{p},
  r = Rotate;
  t = Translate;
  p = RandomReal[q = Pi/2];
  If[n < 0, {},
   Join[
    (t[#, {0, s}] &) /@ (r[#, p, {0, 0}] &) /@ g[n - 1, s*Cos[p]],
    (t[#, s {Cos[p]^2, 1 + Sin[2 p]/2}] &) /@ (r[#, p - q, {0, 0}] &) /@
       g[n - 1, s*Sin[p]],
    {Rectangle[{0, 0}, {s, s}]}
    ]
   ]
  ]
f = Graphics@g[#] &
Martin Ender
quelle
Das ist sehr beeindruckend. Schade, dass ich kein mathematica zum Testen habe - könnten Sie noch ein paar Beispielausgaben hinzufügen?
Alexander-Brett
@ Ali0sha siehe Bearbeiten
Martin Ender
Sie brauchen dort nicht rein Showund Modulesind auch unnötig.
Swish
@swish Danke für den ShowHinweis, aber wie kann ich das loswerden Module? Wenn ich plocal nicht deklariere , wird es in den rekursiven Aufrufen überschrieben, sodass ich nicht beide Aufrufe mit demselben ausführen kann p, oder?
Martin Ender
@m.buettner Vielleicht kannst du das verwenden Block, das kürzer ist als Module.
Alephalpha
20

CFDG, 134 Zeichen

Dieser ist nicht genau gültig, da Sie die Rekursionstiefe nicht einschränken können. Aber das Problem nur Anrufe für eine Lösung in diesem . :)

startshape t
c(q)=cos(q/2)^2
d(q)=1+sin(q)/2
p=acos(-1)
shape t{w=rand(p)
SQUARE[x .5 .5]t[trans 0 1 c(w) d(w)]t[trans c(w) d(w) 1 1]}

Die Ergebnisse sehen ungefähr so ​​aus

Bildbeschreibung hier eingeben

Für weitere 46 Zeichen (insgesamt 180 Zeichen ) können Sie es sogar einfärben:

startshape t
c(q)=cos(q/2)^2
d(q)=1+sin(q)/2
p=acos(-1)
shape t{w=rand(p)
SQUARE[x .5 .5 h 25 sat 1 b .2]t[trans 0 1 c(w) d(w) b .08 .8 h 2.2]t[trans c(w) d(w) 1 1 b .08 .8 h 2.2]}

Bildbeschreibung hier eingeben

Martin Ender
quelle
Ich weiß, das ist nicht ganz ontopisch, aber wie würde eine Version aussehen, wenn Sie anstelle von "weißem Rauschen" "braunes Rauschen" als Winkel verwenden würden?
30.
@Synthetica meinst du mit mehr Winkeln um 90 ° und weniger bei 0 und 180?
Martin Ender
@Synthetica Ähnlich . Ich konnte kein tatsächliches Random-Walk-Rauschen implementieren, da dazu ein Eingabeparameter (der letzte zufällige Wert) erforderlich ist, der angepasst und weitergegeben wird. Dies würde die Grammatik kontextsensitiv machen und wird daher von CFDG nicht unterstützt. Ich habe es leicht vorgetäuscht, indem ich die Zufallswerte einfach mit einer einfachen kubischen Funktion auf der Zufallsstichprobe ein bisschen mehr in Richtung π / 2 verschoben habe.
Martin Ender
Ich denke, dass Ihr Imgur-Link kaputt ist, und obwohl ich die Farbe und Form sehr
mag
@ ali0sha du hast recht, hier ist der feste link . Dieses zu disqualifizieren ist absolut fair. Ich wollte Context Free Art nur mit einigen Leuten teilen und es schien ein guter Ansatz für das Problem zu sein. ;) ... Nun, ich habe immer noch die Mathematica-Antwort ^^
Martin Ender
4

Postscript, 322 270

Bearbeiten: Es realtimesieht so aus, als könne kein richtiger Zufallsgenerator-Startwert verwendet werden. Daher verwenden wir für diesen Zweck die Umgebungsvariable und führen das Programm folgendermaßen aus:

gs -c 20 $RANDOM -f tree.ps

oder

gswin32c -c 20 %RANDOM% -f tree.ps

Jetzt sind unsere Bäume weniger vorhersehbar. 14 Bytes werden zur Gesamtanzahl hinzugefügt. Sonstige Änderungen: 1) Das Programmargument wird jetzt in der Befehlszeile übergeben. 2) Zu diesem Zweck dient keine explizite Iterationszählstapelgröße (der Rotationswinkel des linken Zweigs wird auf dem Stapel gespeichert, um später den rechten Zweig zu zeichnen). 3) Es gibt keine benannte Variable für die erforderliche Tiefe - die Stapelgröße ist der Versatz auf dem Stapel. Es bleibt dort beim Verlassen, dh es wird nicht verbraucht.

srand
250 99 translate
50 50 scale
/f{
    count
    dup index div dup 1 le{
        0 exch 0 setrgbcolor
        0 0 1 1 rectfill
        0 1 translate
        rand 5 mod 1 add 15 mul
        gsave
        dup rotate
        dup cos dup scale
        f
        grestore
        dup cos dup dup mul
        exch 2 index sin mul translate
        dup 90 sub rotate
        sin dup scale 1
        f
        pop
    }{pop}ifelse
}def
f

Ich denke, es ist ziemlich offensichtlich - der Grafikstatus ist vorbereitet und die fProzedur wird für jede aufeinanderfolgende Tiefenebene zweimal rekursiv aufgerufen - für 'linke' und 'rechte' Zweige. Das Arbeiten mit einem Rechteck mit der 1x1Größe (siehe Originalmaßstab) erspart die Multiplikation mit der Seitenlänge. Der Drehwinkel des linken Zweigs ist zufällig gewählt - es wird eine von 5 zufälligen, gleichmäßig verteilten Unterteilungen verwendet - ich denke, dies verhindert mögliche hässliche Fälle für eine gleichmäßige Zufälligkeit.

Bei einer erforderlichen Tiefe von mehr als 20 kann es langsam sein.

Als nächstes folgt die Golfversion mit ASCII-codierten binären Token (siehe die Antwort von luser droog aus dem verlinkten Thema). Beachten Sie , cos, sin, randkönnen diese Schreibweise verwenden.

/${{<920>dup 1 4 3 roll put cvx exec}forall}def srand 250 99<AD>$ 50 50<8B>$/f{count(8X68)$ 1 le{0(>)$ 0<9D>$ 0 0 1 1<80>$ 0 1<AD>$ rand 5 mod 1 add 15<~CecsG2u~>$ cos<388B>$ f(M8)$ cos(88l>)$ 2(X)$ sin<6CAD38>$ 90<A988>$ sin<388B>$ 1 f pop}{pop}(U)$}def f

.

/${{<920>dup 1 4 3 roll put cvx exec}forall}def
srand
250 99<AD>$
50 50<8B>$
/f{
count(8X68)$
1 le{
0(>)$ 0<9D>$
0 0 1 1<80>$
0 1<AD>$
rand 5 mod 1 add 15 
<~CecsG2u~>$
cos<388B>$ 
f
(M8)$
cos(88l>)$
2(X)$ sin<6CAD38>$
90<A988>$ sin<388B>$
1
f
pop
}{pop}(U)$
}def
f

Bildbeschreibung hier eingeben

user2846289
quelle
Ich denke, der Stil hier ist, dass Kommandozeilenargumente hinzugefügt werden müssen, damit dies 344 ergibt ... Ich muss sagen, dass dies selbst für Codegolf-Verhältnisse ziemlich beeindruckend fremd aussieht. Wie weit kommen Sie mit binären Token? Sie sind nicht weit weg von Mathematica sicher
Alexander-Brett
@ ali0sha, -dGraphicsAlphaBitsist ein Flag für die Anti-Alias-Ausgabe, um gezackte Kanten größerer Quadrate zu verhindern. Es kann weggelassen werden (oder in z. B. Umgebungsvariablen 'versteckt' werden). Einige Leute mögen es vielleicht mehr ohne diese Flagge (Baumblätter bekommen mehr "Volumen"). Nun, diese 20 Bytes sind nicht so wichtig. Ich würde sagen, 20-25% Rabatt bei Verwendung von ASCII-codierten binären Token (gemessen an der Antwort auf ein verknüpftes Thema). Möglicherweise 50% Rabatt ohne ASCII-Codierung, 2 binäre Bytes pro Systemnamens-Token.
Sieht
Ich denke, Sie sollten es tun - machen Sie es hier ein bisschen wettbewerbsfähiger :)
Alexander-Brett
3

Coffeescript 377B 352B

Ich fühle mich beim Schreiben von Coffeescript schmutzig, aber ich kann kein anständiges Zeichenpaket für python3 finden: - /

Q=(n)->X=(D=document).body.appendChild(C=D.createElement('Canvas')).getContext('2d');C.width=C.height=400;M=Math;T=[[175,400,50,i=0]];S=M.sin;C=M.cos;while [x,y,l,a]=T[i++]
 X.save();X.translate x,y;X.rotate -a;X.fillRect 0,-l,l,l;X.restore();T.push [e=x-l*S(a),f=y-l*C(a),g=l*C(b=M.random()*M.PI/2),d=a+b],[e+g*C(d),f-g*S(d),l*S(b),d-M.PI/2] if i<2**n

Javascript 393B 385B

Etwas hübscher in Javascript und ich bin mit der for-Schleife viel zufriedener, aber ohne die Syntax [x, y, z] = Ich kann es einfach nicht kurz genug machen, um Coffeescript zu übertreffen

function Q(n){X=(D=document).body.appendChild(C=D.createElement('Canvas')).getContext('2d');C.width=C.height=600;M=Math;T=[[275,400,50,i=0]];while(A=T[i++]){X.save();X.translate(x=A[0],y=A[1]);X.rotate(-(a=A[3]));X.fillRect(0,-(l=A[2]),l,l);X.restore();S=M.sin;C=M.cos;i<M.pow(2,n)&&T.push([e=x-l*S(a),f=y-l*C(a),g=l*C(b=M.random()*M.PI/2),d=a+b],[e+g*C(d),f-g*S(d),l*S(b),d-M.PI/2])}}

Ich muss sagen, ich bin ein bisschen verärgert, das ist fast doppelt so lang wie die Mathematica-Lösung: - / sehe es in Aktion: http://jsfiddle.net/FK2NX/3/

Alexander-Brett
quelle
Ein paar Vorschläge: Sie können mindestens 16 Zeichen speichern, indem Sie in CoffeeScript Semikolons anstelle von Zeilenumbrüchen verwenden. In beiden Fällen kann eine der Methoden eingeschaltet werdenX Rückgabe Xverketten. Und Sie können durch die Einsparung wieder ein gutes Bündel von Zeichen speichern M.sinund M.cosin Variablen mit einem Zeichen.
Martin Ender
Leider geben Kontextoperationen nicht den Kontext zurück, von dem ich ziemlich verärgert war. Sie können auch M.sin in Ms umbenennen, aber die Zeile Ms = M.sin nimmt mehr Zeichen auf als es speichert ... Ich werde die Leerzeichen entfernen.
Alexander-Brett
Nein, das kannst du einfach tun s=M.sin .
Martin Ender
Wieso kann ich S = M.sin, aber nicht R = X.rotieren?
Alexander-Brett
Schätze ich rotate verwendet thisund sinnicht. Sie müssten so etwas tun R=X.rotate.bind(X), aber das ist es wahrscheinlich nicht mehr wert.
Martin Ender