Spielen Sie das Chaos-Spiel

28

Das Chaos-Spiel ist eine einfache Methode, um Fraktale zu generieren. Führen Sie unter der Annahme eines Startpunkts, eines Längenverhältnisses r und einer Menge von 2D-Punkten wiederholt Folgendes aus:

  • Wählen Sie aus Ihrem Punktesatz einen Punkt nach dem Zufallsprinzip (einheitlich) aus.
  • Dieser Punkt und der zuletzt gezogene Punkt (oder der Startpunkt) werden gemittelt, wobei r und 1 - r als Gewicht verwendet werden (dh r = 0 bedeutet, dass Sie den Startpunkt erhalten, r = 1 bedeutet, dass Sie den Zufallspunkt erhalten, und r = 0,5 bedeutet, dass Sie den Punkt auf halbem Weg dazwischen bekommen.)
  • Zeichnen Sie den resultierenden Punkt.

Wenn Sie beispielsweise die Eckpunkte eines gleichseitigen Dreiecks und r = 0,5 auswählen, werden die eingezeichneten Punkte ein Sierpinski-Dreieck darstellen:

Bildbeschreibung hier eingeben

Bild auf Wikipedia gefunden

Sie müssen ein Programm oder eine Funktion schreiben, die das Chaos-Spiel "spielt", um ein Fraktal zu erstellen.

Eingang

Sie können entweder ein Programm oder eine Funktion schreiben und folgende Eingaben über ARGV, STDIN oder Funktionsargument vornehmen:

  • Die Anzahl der zu zeichnenden Punkte.
  • Die Startkoordinate (die auch eingetragen werden muss!).
  • Das Durchschnittsgewicht r im Intervall [0,1] .
  • Eine Liste mit Punkten zur Auswahl.

Ausgabe

Sie können auf dem Bildschirm rendern oder eine Bilddatei schreiben. Wenn das Ergebnis gerastert wird, muss es auf jeder Seite mindestens 600 Pixel betragen, alle Punkte müssen sich auf der Leinwand befinden und mindestens 75% der horizontalen und vertikalen Ausdehnung des Bildes müssen für Punkte verwendet werden (dies ist zu vermeiden) Antworten mit einem einzelnen schwarzen Pixel, das sagt "es ist wirklich weit herausgezoomt"). Die x- und y- Achse müssen auf derselben Skala liegen (dh die Linie von (0,0) bis (1,1) muss einen Winkel von 45 Grad haben), und jeder im Chaosspiel geplottete Punkt muss als einzelner Punkt dargestellt werden Pixel (wenn Ihre Plotmethode den Punkt als Anti-Aliase darstellt, kann er über 2x2 Pixel verteilt sein).

Sie haben die Wahl zwischen Farben, aber Sie benötigen mindestens zwei unterscheidbare Farben: eine für den Hintergrund und eine für die Punkte, die während des Chaos-Spiels gezeichnet werden. Möglicherweise müssen Sie die Eingabepunkte zeichnen, aber nicht.

Bitte fügen Sie Ihrer Antwort drei interessante Beispielausgaben bei.

Wertung

Dies ist Codegolf, daher gewinnt die kürzeste Antwort (in Bytes).

Bearbeiten: Sie müssen die Eingabepunkte nicht mehr zeichnen, da sie ohnehin nicht wirklich als einzelne Pixel sichtbar sind.

Martin Ender
quelle
Was bedeutet " jeder geplottete Punkt ... muss als einzelnes Pixel dargestellt werden "? Ist es a), dass kein Anti-Aliasing verwendet werden sollte? oder b) dass die Anzahl der Punkte in der zweiten Farbe gleich dem ersten Punkt aus der Eingabe sein muss? Beachten Sie, dass b) nur garantiert werden kann, wenn für die Iterationsprozedur der Test "Fällt dieses Pixel mit einem zuvor gezeichneten Pixel zusammen?" Vorliegt. Wenn der Zufallszahlen-Selektor den gleichen Punkt mehrmals hintereinander auswählt, konvergiert die Position zu dieser Punkt.
Peter Taylor
@PeterTaylor Es sollte vermieden werden, dass Leute große Punkte als Punkte zeichnen (wie dies in Mathematica standardmäßig der Fall ist), aber ich habe bereits bemerkt, dass Anti-Aliasing einige Probleme mit der Sicherstellung einzelner Pixel in Sohams Antwort verursacht. Ich denke, ich werde das lockern, um "nicht größer als 2x2 Pixel" zu sein, was alle Anti-Aliasing-Probleme abdecken sollte.
Martin Ender
Ich glaube, ich habe etwas falsch verstanden: Sie nehmen immer den Mittelwert des zuletzt aufgezeichneten Punkts und einen zufälligen Punkt der aktuellen Liste. Dann fügen Sie diesen neuen Punkt der Liste hinzu. Ist das korrekt? Es scheint, dass wenn Sie viele Punkte in einer "Ecke" haben, Sie viel mehr dort bekommen, aber es ist unwahrscheinlich, dass es aus dieser Wolke herauskommt - zumindest "konvergiert" mein Code immer ziemlich schnell zu Punkten, die zu nahe beieinander liegen wirklich das Bild verbessern.
Fehler
1
@flawr nein, du fügst den neuen Punkt nicht zur Liste hinzu. Die Liste ist fest - der Algorithmus kümmert sich nur um den letzten Punkt, der geplottet wurde, nicht um die Punkte davor.
Nathaniel
Danke, das erklärt viel, sollte vielleicht in der Frage geklärt werden.
Fehler

Antworten:

8

Mathematica, 89

f[n_,s_,r_,p_]:=Graphics@{AbsolutePointSize@1,Point@NestList[#-r#+r RandomChoice@p&,s,n]}

f[10000, {0, 0}, .5, {{-(1/2), Sqrt[3]/2}, {-(1/2), -(Sqrt[3]/2)}, {1, 0}}]

Mathematica-Grafiken

Wie es funktioniert

In Mathematica Graphics[]erzeugt die Funktion skalierbare Grafiken. Sie rendern sie auf die gewünschte Größe, indem Sie einfach die Bildecken ziehen. Tatsächlich handelt es sich bei der Anfangsgröße aller angezeigten Grafiken um eine ".ini" -Einstellung, die Sie auf 600 oder einen anderen gewünschten Wert festlegen können. Für die 600x600-Anforderung müssen also keine besonderen Maßnahmen ergriffen werden.

Das AbsolutePointSize[]Ding legt fest, dass die Punktgröße durch Vergrößern der Bildgröße nicht verändert wird.

Das Kernkonstrukt ist

 NestList[#-r#+r RandomChoice@p&,s,n]

oder in nicht-golfed Pseudo-Code:

 NestList[(previous point)*(1-r) + (random vertex point)*(r), (start point), (iterations)]

Es wird rekursiv eine Liste erstellt (start point), die mit der (vektoriellen) Funktion im ersten Argument beginnt und auf jeden nachfolgenden Punkt angewendet wird, wobei schließlich die Liste aller berechneten Punkte zurückgegeben wird, die geplottet werden sollenPoint[]

Beispiele für die Selbstreplikation:

Grid@Partition[Table[
   pts = N@{Re@#, Im@#} & /@ Table[E^(2 I Pi r/n), {r, 0, n - 1}];
   Framed@f[10000, {0, 0}, 1/n^(1/n), pts], {n, 3, 11}], 3]

Mathematica-Grafiken

Dr. belisarius
quelle
@ MartinBüttner Instructions for testing this answer without Mathematica installed:1) Laden Sie dies aus dem Pastebin herunter und speichern Sie es als * .CDF. 2) Laden Sie die kostenlose CDF-Umgebung von Wolfram Research unter (keine kleine Datei) herunter und installieren Sie sie . Genießen. Sag mir, ob es funktioniert!
Dr. Belisarius
Ihre golfed Version funktioniert nicht ganz (zumindest auf V10): Sie müssen wechseln um #rzu r#ohne Leerzeichen wegzukommen oder *dazwischen.
Martin Ender
@ MartinBüttner Neugierig! Es funktioniert wie ein Zauber in Version 9 (ich habe noch keine Version 10). Jedenfalls habe ich (blind) das #und getauscht r.
Dr. Belisarius
Ah, es ist eine neue Funktion. Sie können jetzt Funktionen auf Assoziationen anwenden. In diesem Fall erhalten Sie benannte Parameter, auf die über zugegriffen werden kann #key. Ich bin sicher, das wird nützlich sein. :)
Martin Ender
8

Java: 246 253 447

Als eine Funktion m():

void m(float[]a){new java.awt.Frame(){public void paint(java.awt.Graphics g){int i=0,x=i,y=i,v;for(setSize(832,864),x+=a[1],y+=a[2];i++<=a[0];v=a.length/2-2,v*=Math.random(),x+=(a[v+=v+4]-x)*a[3],y+=(a[v+1]-y)*a[3])g.drawLine(x,y,x,y);}}.show();}

Zeilenumbrüche (innerhalb eines Programms, um die Verwendung anzuzeigen):

class P{
    public static void main(String[]a){
        new P().m(new float[]{1000000,            // iterations
                              416,432,            // start
                              0.6f,               // r
                              416,32,16,432,      // point list...
                              416,832,816,432,
                              366,382,366,482,
                              466,382,466,482});
    }

    void m(float[]a){
        new java.awt.Frame(){
            public void paint(java.awt.Graphics g){
                int i=0,x=i,y=i,v;
                for(setSize(832,864),x+=a[1],y+=a[2];
                    i++<=a[0];
                    v=a.length/2-2,v*=Math.random(),
                    x+=(a[v+=v+4]-x)*a[3],
                    y+=(a[v+1]-y)*a[3])
                    g.drawLine(x,y,x,y);
            }
        }.show();
    }
}

Das Zeichnen von Eingabepunkten wurde aus den Anforderungen entfernt (yay 80 Bytes!). Sie werden immer noch in den alten Screenshots unten gezeigt, aber nicht angezeigt, wenn Sie es ausführen. Bei Interesse den Versionsverlauf einsehen.

Die Eingaben werden als Array von Floats angegeben. Das erste sind Iterationen, die nächsten beiden beginnen x y. Viertens ist rund zuletzt kommt die Liste der Koordinaten in x1 y1 x2 y2 ...Mode.

Ninja Stern

1000000 400 400 0.6 400 0 0 400 400 800 800 400 350 350 350 450 450 350 450 450

Bildbeschreibung hier eingeben

Kreuz

1000000 400 400 0.8 300 0 500 0 500 300 800 300 800 500 500 500 500 800 300 800 300 500 0 500 0 300 300 300

Bildbeschreibung hier eingeben

Oktoketten

1000000 400 400 0.75 200 0 600 0 800 200 800 600 600 800 200 800 0 600 0 200

Bildbeschreibung hier eingeben

Geobits
quelle
Dies funktioniert nicht auf meinem Computer und Java-Beschwerden showsind veraltet
stolzer Haskeller
@proudhaskeller show() ist veraltet, aber es funktioniert immer noch. Wenn Sie sagen "funktioniert nicht", was bedeutet das? Wenn Sie nicht über Java 8 verfügen, müssen Sie mindestens ein finalto String[]ain main hinzufügen .
Geobits
Portierte deine Antwort auf Processing und schnitt 100 Zeichen ab.
user12205
1
@ace Schön. Sie können das mit so ziemlich jedem Java-Golf für die grafische Ausgabe tun, aber ich mag, dass es genau 100 Zeichen sind: D
Geobits
7

JavaScript (E6) + Html 173 176 193

Edit: Big Cut, danke an William Barbosa

Edit: 3 Bytes weniger dank DocMax

173 Bytes, die die Funktion und das Canvas-Element zählen, die zur Anzeige der Ausgabe erforderlich sind.

Testen Sie das Speichern als HTML-Datei und öffnen Sie es in FireFox.

JSFiddle

nett


Maske


Schnee


Teppich


<canvas id=C>
<script>
F=(n,x,y,r,p)=>{
  for(t=C.getContext("2d"),C.width=C.height=600;n--;x-=(x-p[i])*r,y-=(y-p[i+1])*r)
    i=Math.random(t.fillRect(x,y,1,1))*p.length&~1      
}
F(100000, 300, 300, 0.66, [100,500, 500,100, 500,500, 100,100, 300,150, 150,300, 300,450, 450,300]) // Function call, not counted
</script>
edc65
quelle
1
<canvas id=C><script>F=(n,x,y,r,p)=>{t=C.getContext("2d"),C.width=C.height=600;for(;n--;)t.fillRect(x,y,1,1),i=Math.random()*p.length&~1,x-=(x-p[i])*r,y-=(y-p[i+1])*r}</script>ist 176 Bytes lang, ich habe Ihre Zählung nicht verstanden
William Barbosa
@ WilliamBarbosa meine Zählung basiert auf meiner Antwort. Mit deinen Hinweisen wird es besser - danke!
EDC65
1
Sie können zwei weitere abschneiden, wenn Sie die forfor(C.width=C.height=600;n--;y-=(y-p[i+1])*r)
Größeninitialisierung verschieben
6

Python - 200 189

import os,random as v
def a(n,s,r,z):
    p=[255]*360000
    for i in[1]*(n+1):
        p[600*s[0]+s[1]]=0;k=v.choice(z);s=[int(k[i]*r+s[i]*(1-r))for i in(0,1)]
    os.write(1,b'P5 600 600 255 '+bytes(p))

Übernimmt Eingaben als Funktionsargumente in ein, schreibt das Ergebnis als pgm-Datei in stdout. nist Iterationen, sist Startpunkt, rist r und zist eine Liste von Eingabepunkten.

Bearbeiten: Zeichnet keine Eingabepunkte mehr in Grau.

Interessante Ergebnisse:

Bildbeschreibung hier eingeben

Iterations: 100000
Starting Point: (200, 200)
r: 0.8
Points: [(0, 0), (0, 599), (599, 0), (599, 599), (300, 300)]

Bildbeschreibung hier eingeben

Iterations: 100000
Starting Point: (100, 300)
r: 0.6
Points: [(0, 0), (0, 599), (599, 0), (300, 0), (300, 300), (0, 300)]

Bildbeschreibung hier eingeben

Iterations: 100000
Starting Point: (450, 599)
r: 0.75
Points: [(0, 0), (0, 300), (0, 599), (300, 0), (599, 300), (150, 450)]
faubi
quelle
Einige gebräuchliche Python-Zeichen speichern: Anfangswerte wie p=[255]*360000können als optionale Parameter für die Funktion verwendet werden. Der Rumpf einer for-Schleife kann sich alle in derselben Zeile befinden, wenn er keinen Kontrollfluss hat. Sie können Parens rasieren von [1]*(n+1)als [1]*-~n; da Sie iin der äußeren for-Schleife nicht verwenden , ist es kürzer, den Code nwie folgt auszuführen:) exec"code;"*n; Ich denke, die Eltern for i in(0,1)können entfernt werden.
25.
6

SuperCollider - 106

SuperCollider ist eine Sprache zum Erzeugen von Musik, kann aber zur Not Grafiken erstellen.

f={|n,p,r,l|Window().front.drawHook_({{Pen.addRect(Rect(x(p=l.choose*(1-r)+(p*r)),p.y,1,1))}!n;Pen.fill})}

Ich habe einige obskure Syntaxverknüpfungen verwendet, um ein paar Bytes zu sparen - eine lesbarere und speichereffizientere Version

f={|n,p,r,l|Window().front.drawHook_({n.do{Pen.addRect(Rect(p.x,p.y,1,1));p=l.choose*(1-r)+(p*r)};Pen.fill})}

bei 109 Zeichen.

Wie im Mathematica-Beispiel müssen Sie die Größe des Fensters manuell ändern, um 600 x 600 Pixel zu erhalten. Sie müssen warten, bis es erneut gezeichnet wird, wenn Sie dies tun.

Dies erzeugt ein einfaches Sierpinsky-Dreieck (wird nicht angezeigt, weil Sie es schon einmal gesehen haben)

f.(20000,100@100,0.5,[0@600,600@600,300@0])

Dadurch entsteht eine Art Sierpinsky-Pentagon:

f.(100000,100@100,1-(2/(1+sqrt(5))),{|i| (sin(i*2pi/5)+1*300)@(1-cos(i*2pi/5)*300)}!5)

Bildbeschreibung hier eingeben

Das gleiche mit 6 Punkten hinterlässt eine umgekehrte Kochschneeflocke in der Mitte:

f.(100000,100@100,1/3,{|i| (sin(i*2pi/6)+1*300)@(1-cos(i*2pi/6)*300)}!6)

Bildbeschreibung hier eingeben

Zum Schluss noch ein Riff über die 3D-Pyramiden aus Aces Antwort. (Beachten Sie, dass ich einen der Punkte zweimal verwendet habe, um den Schattierungseffekt zu erzielen.)

f.(150000,100@100,0.49,[300@180, 0@500,0@500,350@400,600@500,250@600])

Bildbeschreibung hier eingeben

Nathaniel
quelle
6

Python, 189 183 175

Bearbeiten: Das inverse R- Verhältnis wurde korrigiert und auf Schwarzweiß-Bild umgeschaltet, um ein paar Bytes zu sparen.

Nimmt die Anzahl der Punkte als n, den ersten Punkt als p, das Verhältnis als rund die Liste der Punkte als l. Benötigt das Modul Kissen.

import random,PIL.Image as I
s=850
def c(n,p,r,l):
    i=I.new('L',(s,s));x,y=p;
    for j in range(n):w,z=random.choice(l);w*=r;z*=r;x,y=x-x*r+w,y-y*r+z;i.load()[x,s-y]=s
    i.show()

Beispiele:

Ich generiere Punkte im Kreis um die Bildmitte

points = [(425+s*cos(a)/2, 425+s*sin(a)/2) for a in frange(.0, 2*pi, pi/2)]
c(1000000, (425, 425), 0.4, points)

Bildbeschreibung hier eingeben

XOXO-Wiederholungen, einfach das Verhältnis von 0,4 auf 0,6 ändern

Bildbeschreibung hier eingeben

Eine Art Schneeflocke

stars = [(425+s*cos(a)/2,425+s*sin(a)/2) for a in frange(.0,2*pi, pi/4)]
c(1000000, (425, 425), 0.6, stars)

Bildbeschreibung hier eingeben

Das Internet besteht aus Catz
quelle
Keine Ahnung , über die nach hinten Befestigung r Sache, aber Sie können , indem sie dies ein Programm mit ganz wenigen Zeichen speichern n,p,r,l=input(). Sie können die Klammern auch aus den *=Operationen entfernen und verwenden import random as R.
FryAmTheEggman
@FryAmTheEggman Leider macht das Korrigieren meiner Antwort die Optimierung auf *=:( ungültig . Das inputDing wäre gut, wäre sehr unangenehm, damit zu arbeiten, und der Import ist derzeit die prägnanteste Form, die möglich ist (oder habe ich etwas verpasst?).
Internet wird gemacht von catz
Ich bin mir ziemlich sicher, dass die Linie sein kann import random as R,PIL.Image as Iund dann sein random.choicekann R.choice. Ja, die Verwendung von Eingaben ist lahm, aber Sie können die Funktionsversion zum Testen verwenden und die Version veröffentlichen, input()um eine bessere Punktzahl zu erzielen !! 1! : P
FryAmTheEggman
Oh, ich habe gerade bemerkt, dass das Definieren von Zufall 0 Zeichen speichert. Ups: S Wie auch immer, mir ist auch klar geworden, dass Mathe dein Freund ist: y=x*(1-r)+w== y=x-x*r-w.
FryAmTheEggman
@FryAmTheEggman das war mein Punkt: p. Aber danke für die Mathematik.
Internet besteht aus Catz
4

JavaScript (407) (190)

Ich freue mich über Feedback zu meinem Skript und zum Golfen, da ich mit JS nicht vertraut bin.

Lesen Eingang (Um vergleichbar edc65 den Einstieg Ich zähle nicht die Eingabe.):

p=prompt;n=p();[x,y]=p().split(',');r=p();l=p().split(';').map(e=>e.split(','));

Canvas Setup & Berechnung

d=document;d.body.appendChild(c=d.createElement('canvas'));c.width=c.height=1000;c=c.getContext('2d');
for(;n--;c.fillRect(x,y,2,2),[e,f]= l[Math.random()*l.length|0],x-=x*r-e*r,y-=y*r-f*r);

Etwas ungolfed (einschließlich einer Beispieleingabe, bei der die tatsächlichen Eingabeaufforderungen nur auskommentiert sind, also einsatzbereit):

p=prompt;
n=p('n','4000');
[x,y]=p('start','1,1').split(',');
r=p('r','0.5');
l=p('list','1,300;300,1;300,600;600,300').split(';').map(e=>e.split(','));d=document;
d.body.appendChild(c=d.createElement('canvas'));
c.width=c.height=1000;c=c.getContext('2d');
for(;n--;c.fillRect(x,y,2,2),[e,f]= l[Math.random()*l.length|0],x-=x*r-e*r,y-=y*r-f*r);

Beispiele

for(k = 0; k<50; k++){
rad = 10;
l.push([350+rad*k*Math.cos(6.28*k/10),350+rad*k*Math.sin(6.28*k/10)]);
}
r = 1.13;

Bildbeschreibung hier eingeben

r = 0.5;list = [[1,1],[300,522],[600,1],[300,177]];

Bildbeschreibung hier eingeben

r = 0.5
list = [[350+350*Math.sin(6.28*1/5),350+350*Math.cos(6.28*1/5)],
[350+350*Math.sin(6.28*2/5),350+350*Math.cos(6.28*2/5)],
[350+350*Math.sin(6.28*3/5),350+350*Math.cos(6.28*3/5)],
[350+350*Math.sin(6.28*4/5),350+350*Math.cos(6.28*4/5)],
[350+350*Math.sin(6.28*5/5),350+350*Math.cos(6.28*5/5)],


[350+90*Math.sin(6.28*1.5/5),350+90*Math.cos(6.28*1.5/5)],
[350+90*Math.sin(6.28*2.5/5),350+90*Math.cos(6.28*2.5/5)],
[350+90*Math.sin(6.28*3.5/5),350+90*Math.cos(6.28*3.5/5)],
[350+90*Math.sin(6.28*4.5/5),350+90*Math.cos(6.28*4.5/5)],
[350+90*Math.sin(6.28*5.5/5),350+90*Math.cos(6.28*5.5/5)]];

Bildbeschreibung hier eingeben

Fehler
quelle
Welche meinst du?
Fehler
Oh, danke, dass du es mir gesagt hast, ich werde die Einsendung bald aktualisieren!
Fehler
Sie haben meine Antwort verknüpft, aber ich zähle den Aufbau der Zeichenfläche. Ich zähle nur nicht die einzelne Zeile, die die Funktion aufruft. Trotzdem schöne Bilder, vor allem das erste.
Edc65
Ah, das habe ich nicht gemerkt, ich wollte es nur "vergleichbar" machen, aber es ist schwierig, wenn ich mich nur auf JS verlasse =) @ MartinBüttner Aktualisiert, jetzt, da ich es richtig verstanden habe, konnte ich viel davon entfernen der Müll =)
Flawr
3

Processing, 153

Portierte die Java-Antwort von @Geobits auf Processing und spielte etwas mehr Golf, was zu einer Reduzierung von 100 Zeichen führte. Eigentlich wollte ich den Prozess animieren, aber die Eingabebeschränkungen sind zu streng (Processing hat weder stdin noch argv, was bedeutet, dass ich meine eigene Funktion schreiben muss, anstatt die native draw()Schleife von Processing zu verwenden ).

void d(float[]a){int v;size(600,600);for(float i=0,x=a[1],y=a[2];i++<a[0];v=(int)random(a.length/2-2),point(x+=(a[v*2+4]-x)*a[3],y+=(a[v*2+5]-y)*a[3]));}

Komplettes Programm mit Zeilenumbrüchen:

void setup() {
  d(new float[]{100000,300,300,.7,0,600,600,0,600,600,0,0,400,400,200,200,400,200,200,400}); 
}
void d(float[]a){
  int v;
  size(600,600);
  for(float i=0,x=a[1],y=a[2];
      i++<a[0];
      v=(int)random(a.length/2-2),point(x+=(a[v*2+4]-x)*a[3],y+=(a[v*2+5]-y)*a[3]));
}

Das obige Programm gibt Kreuze: Bildbeschreibung hier eingeben

d(new float[]{100000,300,300,.65,142,257,112,358,256,512,216,36,547,234,180,360}); 

Dies gibt Pyramiden: Bildbeschreibung hier eingeben

d(new float[]{100000,100,500,.5,100,300,500,100,500,500});

Dies ergibt das Sierpinski-Dreieck: Bildbeschreibung hier eingeben

user12205
quelle
4
Ich liebe den 3D-Effekt der Pyramiden. :)
Martin Ender
1

Ungolfed "Referenzimplementierung", Python

Update : viel, viel schneller (um Größenordnungen)

Schauen Sie sich die interaktive Shell an!

Bearbeiten Sie die Datei und setzen Sie sie interactiveauf True. Führen Sie dann einen der folgenden Schritte aus:

polygon numberOfPoints numeratorOfWeight denominatorOfWeight startX startY numberOfSides generiert, speichert und zeigt ein Polygon an.

points numberOfPoints numeratorOfWeight denominatorOfWeight startX startY point1X point1Y point2X point2Y ... tut was die Spezifikation verlangt.

Bildbeschreibung hier eingeben

import matplotlib.pyplot as plt
import numpy as np
from fractions import Fraction as F
import random
from matplotlib.colors import ColorConverter
from time import sleep
import math
import sys
import cmd
import time

def plot_saved(n, r, start, points, filetype='png', barsize=30, dpi=100, poly=True, show=False):
    printed_len = 0

    plt.figure(figsize=(6,6))
    plt.axis('off')

    start_time = time.clock()
    f = F.from_float(r).limit_denominator()

    spts = []
    for i in range(len(points)):
        spts.append(tuple([round(points[i].real,1), round(points[i].imag,1)]))

    if poly:
        s = "{}-gon ({}, r = {}|{})".format(len(points), n, f.numerator, f.denominator)
    else:
        s = "{} ({}, r = {}|{})".format(spts, n, f.numerator, f.denominator) 

    step = math.floor(n / 50)

    for i in range(len(points)):
        plt.scatter(points[i].real, points[i].imag, color='#ff2222', s=50, alpha=0.7)

    point = start
    t = time.clock()

    xs = []
    ys = []

    for i in range(n+1):
        elapsed = time.clock() - t
        #Extrapolation
        eta = (n+1-i)*(elapsed/(i+1))
        printed_len = rewrite("{:>29}: {} of {} ({:.3f}%) ETA: {:.3f}s".format(
                s, i, n, i*100/n, eta), printed_len)
        xs.append(point.real)
        ys.append(point.imag)
        point = point * r + random.choice(points) * (1 - r)

    printed_len = rewrite("{:>29}: plotting...".format(s), printed_len)
    plt.scatter(xs, ys, s=0.5, marker=',', alpha=0.3)

    presave = time.clock()
    printed_len = rewrite("{:>29}: saving...".format(s), printed_len)
    plt.savefig(s + "." + filetype, bbox_inches='tight', dpi=dpi)

    postsave = time.clock()
    printed_len = rewrite("{:>29}: done in {:.3f}s (save took {:.3f}s)".format(
                            s, postsave - start_time, postsave - presave),
                            printed_len)

    if show:
        plt.show()
    print()
    plt.clf()

def rewrite(s, prev):
    spaces = prev - len(s)
    sys.stdout.write('\r')
    sys.stdout.write(s + ' '*(0 if spaces < 0 else spaces))
    sys.stdout.flush()
    return len(s)

class InteractiveChaosGame(cmd.Cmd):
    def do_polygon(self, args):
        (n, num, den, sx, sy, deg) = map(int, args.split())
        plot_saved(n, (num + 0.0)/den, np.complex(sx, sy), list(np.roots([1] + [0]*(deg - 1) + [-1])), show=True)

    def do_points(self, args):
        l = list(map(int, args.split()))
        (n, num, den, sx, sy) = tuple(l[:5])
        l = l[5:]
        points = []
        for i in range(len(l)//2):
            points.append(complex(*tuple([l[2*i], l[2*i + 1]])))
        plot_saved(n, (num + 0.0)/den, np.complex(sx, sy), points, poly=False, show=True)

    def do_pointsdpi(self, args):
        l = list(map(int, args.split()))
        (dpi, n, num, den, sx, sy) = tuple(l[:6])
        l = l[6:]
        points = []
        for i in range(len(l)//2):
            points.append(complex(*tuple([l[2*i], l[2*i + 1]])))
        plot_saved(n, (num + 0.0)/den, np.complex(sx, sy), points, poly=False, show=True, dpi=dpi)

    def do_default(self, args):
        do_generate(self, args)

    def do_EOF(self):
        return True

if __name__ == '__main__':
    interactive = False
    if interactive:
        i = InteractiveChaosGame()
        i.prompt = ": "
        i.completekey='tab'
        i.cmdloop()
    else:
        rs = [1/2, 1/3, 2/3, 3/8, 5/8, 5/6, 9/10]
        for i in range(3, 15):
            for r in rs:
                plot_saved(20000, r, np.complex(0,0), 
                            list(np.roots([1] + [0] * (i - 1) + [-1])), 
                            filetype='png', dpi=300)
Soham Chowdhury
quelle
Ohne dies auszuführen , habe ich keine Ahnung, was fantastisch bedeutet. Vielleicht könnten Sie erklären, oder einige Bilder zeigen, was es von den kürzeren unterscheidet?
Geobits
@ Geobits bearbeitet, um Disclaimer und Bild enthalten :)
Soham Chowdhury
4
Ich würde es vorziehen, wenn Sie dies in Ihrer anderen Antwort unter einer separaten Überschrift (z. B. Ungolfed-Referenzimplementierung) angeben, da das Posten von nur ungolfedem Code technisch gesehen "keine Antwort" ist.
Martin Ender
-2

Python (202 Zeichen)

Nimmt die Anzahl der Punkte als n, das Durchschnittsgewicht als r, den Startpunkt als tuple sund die Liste der Punkte als Liste der tupleaufgerufenen XYs l.

import random as v,matplotlib.pyplot as p
def t(n,r,s,l):
 q=complex;s=q(*s);l=[q(*i)for i in l];p.figure(figsize=(6,6))
 for i in range(n):p.scatter(s.real,s.imag,s=1,marker=',');s=s*r+v.choice(l)*(1-r)
 p.show()
Soham Chowdhury
quelle
@ MartinBüttner Entspricht die Tatsache, dass ich eine bestimmte Art von Eingabe mache, der Spezifikation?
Soham Chowdhury
1
Außerdem ist das Ergebnis auf meinem Computer nicht 600 x 600 Pixel, x und y haben unterschiedliche Längenskalen und die Punkte decken mehr als 1 Pixel ab.
Martin Ender