Die Flagge der Vereinigten Staaten von Amerika enthält in ihrem Kanton 50 Sterne, die die 50 Staaten repräsentieren.
In der Vergangenheit, als es weniger Staaten gab, gab es natürlich weniger Sterne, und sie waren unterschiedlich angeordnet. Zum Beispiel gab es von 1912 bis 1959 (nach der Aufnahme von New Mexico und Arizona, aber vor Alaska) 48 Sterne in einer rechteckigen Anordnung von 6 × 8.
Die 37-Sterne-Flagge von 1867 bis 1877 (nach der Zulassung von Nebraska, aber vor Colorado) hatte ein asymmetrisches Sternchenmuster.
Für den Fall, dass in Zukunft ein 51. Staat hinzukommt, hat das Army Institute of Heraldry bereits einen vorläufigen Entwurf für eine neue Flagge entwickelt.
Aber es gibt keine General Algorithmus zum Anordnen der Sterne, also lasst uns einen erstellen!
Die Herausforderung
Schreiben Sie ein Programm, das für eine bestimmte Anzahl von Sternen, die im Kanton (blauer Teil) einer US-Flagge platziert werden sollen, optimale Koordinaten ausgibt, an denen diese Sterne platziert werden sollen. Das Koordinatensystem wird mit dem Kanton festgelegt [ nicht der Flagge als Ganzes] mit 0 ≤ x ≤ W und 0 ≤ y ≤ H definiert.
Für diese Herausforderung wird eine „optimale“ Anordnung definiert, die den mittleren (euklidischen) Abstand zwischen einem Punkt im Kanton und dem Zentrum des nächsten Sterns minimiert.
Ein einfacher (wenn auch nicht optimaler) Algorithmus zur Annäherung an diesen Wert lautet:
def mean_distance_to_nearest_star(stars, width, height, point_density=100):
"""
Approximate the mean distance between a point in the rectangle
0 < x < width and 0 < y < height, and the nearest point in stars.
stars -- list of (x, y) points
width, height -- dimensions of the canton
"""
total = 0.0
nx = round(width * point_density)
ny = round(height * point_density)
for ix in range(nx):
x = (ix + 0.5) * width / nx
for iy in range(ny):
y = (iy + 0.5) * width / ny
min_dist = float('inf')
for sx, sy in stars:
min_dist = min(min_dist, math.hypot(x - sx, y - sy))
total += min_dist
return total / (nx * ny)
Ihr Programm muss drei Befehlszeilenargumente annehmen (ohne den Programmnamen selbst zu zählen):
- Die Anzahl der Sterne, die im Kanton platziert werden sollen.
- Die Breite des Kantons. (Muss Gleitkommawerte akzeptieren.)
- Die Höhe des Kantons. (Muss Gleitkommawerte akzeptieren.)
(Wenn Ihre bevorzugte Programmiersprache keine Befehlszeilenargumente unterstützt, tun Sie etwas ziemlich Äquivalentes und dokumentieren Sie es in Ihrer Antwort.)
Die Ausgabe sollte aus durch Kommas getrennten X- und Y-Werten bestehen, und zwar eins zu einer Zeile. (Reihenfolge der Punkte spielt keine Rolle.)
Beispielsweise:
~$ flagstar 5 1.4 1.0
0.20,0.20
0.20,0.80
0.70,0.50
1.20,0.20
1.20,0.80
Zusätzliche Regeln und Hinweise
- Ich habe jederzeit das Recht, Regelungslücken zu schließen.
Die Antwortfrist endet am Freitag, den 4. Juli, um 24:00 Uhr (UTC-05: 00).Aufgrund fehlender Antworten wurde die Frist verlängert. TBA.- Nehmen Sie in Ihre Antwort auf:
- Der Code Ihres Programms
- Eine Erklärung, wie es funktioniert
- Seine Ausgabe mit den Befehlszeilenargumenten
50 1.4 1.0
- Ihr Programm muss innerhalb eines angemessenen Zeitraums ausgeführt werden: Höchstens 5 Minuten auf einem typischen PC. Ich werde nicht streng genug sein, aber dein Programm disqualifizieren, wenn es Stunden dauert .
- Ihr Programm muss deterministisch sein, dh für dieselben Argumente immer genau dieselbe Ausgabe liefern. Also, hängen Sie nicht von
time()
oder abrand()
. Monte-Carlo-Methoden sind in Ordnung, solange Sie Ihren eigenen PRNG rollen. - Nur die Mittelpunkte der Sterne sind von Bedeutung. Machen Sie sich keine Sorgen, wenn Sie versuchen, Überschneidungen oder ähnliches zu vermeiden.
Wertung
- Minimieren Sie die mittlere Entfernung von einem Punkt im Kanton zum nächsten Stern. (Siehe oben.)
- Sie können anhand historischer US-Flaggen zwischen 13 und 50 Sternen bewertet werden. Der genaue Algorithmus zum Gewichten von Ergebnissen in einer einzelnen Rangfolge wird später veröffentlicht.
- Im Falle eines Gleichstands wird der Gewinner anhand der Anzahl der Nettostimmen ermittelt.
- Ich werde wahrscheinlich ein eigenes Programm veröffentlichen, mich jedoch von der Berechtigung für das Häkchen ausschließen.
quelle
Antworten:
Javascript - bewege Sterne in Richtung des isoliertesten Punktes
(mit einer Animation des Prozesses)
Der Ansatz ist sehr einfach:
Dieser Vorgang wird mehrmals wiederholt, wobei die Bewegung der Sterne allmählich verringert wird. Dies reduziert die maximale Entfernung von einem Punkt zum nächsten Stern und indirekt die mittlere Entfernung von einem Punkt zum nächsten Stern.
Wie in der Frage gefordert, wird hier nicht die eingebaute Zufallsfunktion verwendet, sondern Xorshift .
Ein Großteil des Codes deckt Setup und Animation ab - der Teil, der den Algorithmus anwendet, ist die Funktion
adjustStars
.Code
Sie können den laufenden Prozess im folgenden Stapel-Snippet verfolgen.
Leistung für 50 Sterne
(Breite = 1,4, Höhe = 1,0)
Mittlere Entfernung auf 0,0655106697162357 geschätzt.
Koordinaten:
quelle
Hier ist ein einfaches Beispiel. Es ordnet die Sterne immer in einem rechteckigen Gitter an und optimiert es, indem es die Faktorisierung wählt, bei der die Gitterzellen so nahe wie möglich am Quadrat liegen. Es funktioniert gut, wenn die Anzahl der Sterne einen Divisor nahe der Quadratwurzel hat, und pessimal, wenn die Anzahl der Sterne Primzahl ist.
Leistung für 50 Sterne
(Breite = 1,4, Höhe = 1,0)
Ein 10 × 5 Rechteck.
quelle
Javascript - bewege einen Stern nach dem Zufallsprinzip, wenn sich die mittlere Entfernung verringert
(mit einer Animation des Prozesses)
Dies ist keine so belebte Animation wie meine erste Antwort. Lange Zeiträume ohne Bewegung, da mögliche Umlagerungen getestet und zurückgewiesen werden. Das Endergebnis weist jedoch einen geringeren mittleren Abstand auf, sodass diese Methode eine Verbesserung darstellt.
Der Ansatz ist immer noch sehr einfach:
Dieser Vorgang wird mehrmals wiederholt, wobei die Bewegung der Sterne allmählich verringert wird. Die zufällige Auswahl der zu bewegenden Distanz ist auf kleinere Distanzen ausgerichtet, sodass der Fortschritt in kleinen Änderungen mit gelegentlich größeren Sprüngen durchsetzt ist. Jeder Schritt dauert länger als bei meiner ersten Antwort, da die Messung der mittleren Distanz ein langsamer Prozess ist, bei dem der gesamte Kanton beprobt werden muss.
Wie in der Frage gefordert, wird hier nicht die eingebaute Zufallsfunktion verwendet, sondern Xorshift .
Ein Großteil des Codes deckt Setup und Animation ab - der Teil, der den Algorithmus anwendet, ist die Funktion
adjustStars
.Code
Sie können den laufenden Prozess im folgenden Stapel-Snippet verfolgen.
Leistung für 50 Sterne
(Breite = 1,4, Höhe = 1,0)
Mittlere Entfernung auf 0,06402754713808706 geschätzt.
Koordinaten:
quelle