Ich habe irgendwo über Kreise gelesen und gerade etwas über Discs gelernt ( es ist eigentlich ein ziemlich verbreitetes Konzept ) und über Codegolf nachgedacht.
Ihre Aufgabe ist es, einen Punkt / mehrere Punkte auf einer Scheibe mit dem Radius 1 zufällig zu ordnen .
Regeln:
- Alle Punkte müssen die gleiche Wahrscheinlichkeit haben, um generiert zu werden
- Gleitkommakoordinaten müssen verwendet werden. die Mindestanforderung sind zwei Dezimalstellen (zB die Punkte
(0.12, -0.45)
oder(0.00, -1.00)
sind gültig) - Sie erhalten -20 Bytes, wenn Ihr Programm tatsächlich den Begrenzungskreis und die darin erzeugten Punkte anzeigt. Koordinaten müssen noch gültig sein, aber nicht angezeigt werden, und das erzeugte Bild muss mindestens 201 x 201 Pixel groß sein
- Sie erhalten -5 Bytes, wenn Ihr Programm die Anzahl der zu generierenden Punkte als Eingabe für stdin verwendet
- Wenn Sie den Begrenzungskreis und die Punkte nicht zeichnen möchten, muss Ihr Programm die Punkte ausgeben, die im Format
(x, y)
oder(x,y)
auf stdout generiert wurden - Wenn Sie die Anzahl der generierten Punkte als Eingabe verwenden, aber nicht zeichnen möchten, muss Ihr Programm alle zufälligen Punkte in dem oben angegebenen Format mit oder ohne ein Leerzeichen dazwischen ausgeben
Kürzeste Einsendung in Bytes gewinnt!
code-golf
math
graphical-output
random
Süßkartoffel
quelle
quelle
0.3503082505747327+0.13499221288682994j
.Antworten:
Pyth, 26 - 5 = 21 Bytes
Nimmt die Anzahl der auf stdin zu generierenden Koordinaten und gibt sie wie folgt auf stdout aus:
Verwendet eine Strategie, die der von @ MartinBüttner ähnelt und Polarkoordinaten und Radien generiert, außer dass dabei komplexe Exponentiation verwendet wird.
quelle
p
, nicht wahr? Es ändert nur die Ausgabe in separate Zeilen.CJam,
2827 BytesDiese Lösung basiert nicht auf Ablehnung. Ich generiere die Punkte in Polarkoordinaten, aber mit einer ungleichmäßigen Verteilung der Radien, um eine gleichmäßige Dichte der Punkte zu erreichen.
Teste es hier.
Erläuterung
Warum funktioniert es? Betrachten Sie einen engen Kreisring aus Radius
r
und (kleiner) Breitedr
. Die Fläche ist ungefähr2π*r*dr
(wenn der Kreisring eng ist, sind der innere und der äußere Umfang nahezu identisch, und die Krümmung kann ignoriert werden, so dass die Fläche wie die eines Rechtecks mit Seitenlängen des Umfangs und der Breite des Kreisrings behandelt werden kann) Annulus). Die Fläche wächst also linear mit dem Radius. Das heißt, wir wollen auch eine lineare Verteilung der Zufallsradien, um eine konstante Dichte zu erreichen (bei doppeltem Radius ist doppelt so viel Fläche zu füllen, also wollen wir dort doppelt so viele Punkte).Wie erzeugen wir eine lineare Zufallsverteilung von 0 bis 1? Schauen wir uns zuerst den diskreten Fall an. Nehmen wir an, wir haben eine gewünschte Verteilung von 4 Werten wie
{0.1, 0.4, 0.2, 0.3}
(dh wir wollen1
4-mal so häufig sein wie0
und doppelt so häufig wie2
; wir wollen3
dreimal so häufig sein wie0
):Wie kann man einen der vier Werte mit der gewünschten Verteilung auswählen? Wir können sie stapeln, einen gleichmäßig zufälligen Wert zwischen 0 und 1 auf der y-Achse auswählen und das Segment an diesem Punkt auswählen:
Es gibt jedoch eine andere Möglichkeit, diese Auswahl zu visualisieren. Wir könnten stattdessen jeden Wert der Verteilung durch die Akkumulation der Werte bis zu diesem Punkt ersetzen:
Und jetzt behandeln wir die oberste Zeile dieses Diagramms als Funktion
f(x) = y
und invertieren sie, um eine Funktion zu erhalten , die wir auf einen einheitlich zufälligen Wert anwenden können in :g(y) = f-1(y) = x
y ∈ [0,1]
Cool, wie kann man das nutzen, um eine lineare Radienverteilung zu erzeugen? Dies ist die Distribution, die wir wollen:
Der erste Schritt besteht darin, die Werte der Verteilung zu akkumulieren. Die Verteilung ist jedoch stetig. Anstatt also alle vorherigen Werte zu addieren, nehmen wir ein Integral von
0
bisr
. Wir können leicht die analytisch lösen: . Wir möchten jedoch, dass dies normalisiert wird, dh dass es mit einer Konstanten multipliziert wird, die den Maximalwert von ergibt. Wir möchten also :∫0r r dr = 1/2 r2
1
r
r2
Und schließlich invertieren wir dies, um eine Funktion zu erhalten
[0,1]
, die wir auf einen einheitlichen Wert anwenden können. Dies können wir wiederum analytisch tun: Es ist nurr = √y
, woy
ist der Zufallswert:Dies ist eine ziemlich nützliche Technik, die oft verwendet werden kann, um einfache Verteilungen genau zu generieren (sie funktioniert für jede Verteilung, aber für komplizierte müssen die letzten beiden Schritte möglicherweise numerisch gelöst werden). Ich würde es jedoch in diesem speziellen Fall nicht im Produktionscode verwenden, da die Quadratwurzel, der Sinus und der Cosinus unerschwinglich teuer sind: Die Verwendung eines auf Ablehnung basierenden Algorithmus ist im Durchschnitt viel schneller, da nur Addition und Multiplikation erforderlich sind.
quelle
Mathematica,
6844 - 20 = 24 BytesVielen Dank an David Carraher, der mir mitteilte
RandomPoint
, dass 24 (!) Bytes eingespart wurden. In Mathematica ist für alles etwas eingebaut.Dies stellt den Punkt und den Begrenzungskreis dar, um sich für den Bonus zu qualifizieren:
Das Ergebnis ist ein Vektorbild, daher ist die Größenangabe von 201 x 201 Pixel nicht wirklich sinnvoll, wird jedoch standardmäßig größer dargestellt.
quelle
Graphics[{Circle[], Point@RandomPoint@Disk[]}]
?Graphics@{Circle[], Point@RandomPoint@Disk[]}
,
.CJam,
3126 BytesDies funktioniert, indem wiederholt zufällige Punkte in einem Quadrat der Seitenlänge 2 erzeugt werden und der erste Punkt, der in die Einheitsscheibe fällt, beibehalten wird.
Danke an @ MartinBüttner für das Golfen mit 3 Bytes!
Probieren Sie es online im CJam-Interpreter aus .
Wie es funktioniert
quelle
iKe ,
5351 BytesNichts besonderes, aber ich nehme an, wir sollten mindestens eine grafische Lösung haben:
Versuchen Sie es in Ihrem Browser .
Bearbeiten: Ich kann zwei Bytes abschneiden, indem ich den @ MartinBüttner-Ansatz zum Ändern der Verteilung von Polarkoordinaten anwende. Ich denke, es ist auch etwas direkter:
quelle
Perl, 59 Bytes
Dies ist nur eine einfache Lösung, bei der Punkte in einem Quadrat generiert und zu weit entfernte Punkte verworfen werden. Mein einzigartiger Golf-Trick ist es, die Aufgaben in die Bedingung einzubeziehen.
Bearbeiten: Während des Golfspiels habe ich eine interessante Möglichkeit gefunden, zufällige Punkte auf einen Kreis zu drucken .
quelle
Oktave,
2453 - 20 = 33 BytesErzeugt 501 Theta-Werte mit gleichem Abstand plus eine Zufallszahl und skaliert sie alle auf [0..2π]. Dann werden 501 Einsen für den Radius des Kreises sowie ein zufälliger Radius für den Punkt generiert und die Quadratwurzel verwendet, um eine gleichmäßige Verteilung über die Scheibe sicherzustellen. Zeichnet dann alle Punkte als Polarkoordinaten.
Hier ist eine kurze Demonstration der Verteilung (ohne den Einheitenkreis):
quelle
Oktave / Matlab,
7464 BytesAblehnungsmethode , 64 Bytes:
Direkte Methode , 74 Bytes (danke an Martin Büttner für die Hilfe bei der Korrektur von zwei Fehlern):
quelle
R,
999581-20 =797561 BytesVerwenden Sie die komplexe Zahlenkonstruktion, um die x / ys aus Polarkoordinaten zu erstellen. Die Eingabe war etwas teuer und es gibt wahrscheinlich einen besseren Weg, dies zu tun. Mit
ylim
undsoll sichergestellt werden, dass der gesamte Kreis gezeichnet wird, und mit wirdxlim
asp
sichergestellt, dass die Punkte unter dem Kreissymbol angezeigt werden.Vielen Dank an @jbaums und @flodel für die Einsparungen
Probieren Sie es hier aus
quelle
runif(9,0,1)
kann vereinfacht werdenrunif(9)
symbols(0,0,1,i=F,asp=1,ylim=c(-1,1));points(complex(,,,runif(9),runif(9,-1)*pi))
yli
anstelle vonylim
.Processing / Java 141 bytes-20 = 121
Die Anforderung für 201 * 201 als Mindestgröße erfordert, dass ich die
setup
Methode eingebe, da Processing.org standardmäßig 200x200 ist :(quelle
QBasic, 138 Bytes - 20 - 5 = 113
Nimmt Benutzereingaben auf und zeichnet die Disc und Punkte. Getestet auf QB64 .
Dies ist eine ziemlich einfache Strategie, mit der man auf die Dartscheibe wirft und behält, was man hält. Der Haken dabei ist, dass "was klebt" nicht mathematisch, sondern grafisch bestimmt wird: Eine weiße Scheibe wird auf einem schwarzen Hintergrund dargestellt, und dann werden zufällig erzeugte Punkte verworfen, bis sie nicht mehr schwarz sind. Die Punkte selbst sind blau gezeichnet (obwohl es schwer zu erkennen ist, wann es sich um einzelne Pixel handelt - klicken Sie auf das Bild, um es zu vergrößern).
quelle
awk - 95 - 5 = 90
Da ich mir bezüglich des Teils rand () <. 5 nicht ganz sicher war, habe ich mit diesem Skript einige Verteilungstests durchgeführt:
was bei einer Eingabe von 1e7 zu diesem Ergebnis führt, nachdem ich ein- oder zweimal an meinem Kaffee getrunken habe:
das finde ich ganz in ordnung.
Eine kleine Erklärung:
Nach einigem Kritzeln stellte sich heraus, dass die Radien, in die Sie schneiden müssten, sqrt (1/4), sqrt (1/2) sind, wenn Sie die Scheibe in vier Ringe mit gleicher Fläche teilen möchten ) und sqrt (3/4). Da der tatsächliche Radius des Punktes, den ich teste, sqrt (x ^ 2 + y ^ 2) wäre, kann ich die Quadratwurzel alle zusammen überspringen. Das 1/4, 2/4, 3/4 "Zusammentreffen" könnte mit dem zusammenhängen, worauf M. Buettner früher hingewiesen hat.
quelle
HPPPL , 146 (171-20-5) Bytes
Beispiel für 10000 Punkte (einschließlich der Zeitangabe in Sekunden für das reale Gerät):
Die Funktion selbst wird von aufgerufen
r(n)
. Der Rest auf dem Bild oben dient nur zu Timing-Zwecken.Ergebnis (Scheibendurchmesser beträgt 236 Pixel):
In der obigen Version werden die Punktkoordinaten nicht gespeichert, daher habe ich eine Version geschrieben, die zwei Parameter akzeptiert
r(n,p)
.n
ist die Anzahl der Punkte undp=0
gibt die Punkte an das Terminal zurück,p=1
zeichnet die Punkte und die Disc), falls das Speichern von Koordinaten obligatorisch ist. Diese Version ist 283 (308-20-5) Bytes lang:Die ungolfed Version:
Terminalausgang für
r(10,0)
:r(10,1)
zeigt die Scheibe mit den Punkten, wie oben gezeigt.quelle
JavaScript, 75 Byte
Ablehnungsbasiert:
Direkte Methode (80 Bytes):
quelle
Python,
135-130BytesDer
**0.5
Dank an den Vorschlag von @ jimmy23013 wurde entfernt (da es sich um einen Einheitskreis handelt, überprüfe ich jetzt, ob der quadratische Abstand zwischen (x, y) und (0, 0) gleich 1 2 ist . Dies ist dasselbe).Dadurch konnte ich auch die Klammern entfernen.
quelle
**0.5
.