Hintergrund
Ein pythagoreisches Dreieck ist ein rechtwinkliges Dreieck, bei dem jede Seitenlänge eine ganze Zahl ist (dh, die Seitenlängen bilden ein pythagoreisches Dreifach ):
Mit den Seiten dieses Dreiecks können wir zwei weitere nicht kongruente pythagoreische Dreiecke wie folgt anfügen:
Wir können mit diesem Muster weitermachen, solange sich keine zwei Dreiecke überlappen und die Verbindungsseiten gleich lang sind:
Die Frage ist, wie viele nicht kongruente pythagoreische Dreiecke können wir in einen bestimmten Raum einpassen?
Die Eingabe
Sie erhalten zwei Ganzzahlen als Eingabe W
und H
über Funktionsargumente STDIN, Zeichenfolgen oder was auch immer Sie möchten. Die Ganzzahlen können als Dezimal-, Hexadezimal-, Binär-, Unär- (Viel Glück, Retina ) oder eine beliebige andere Ganzzahlbasis empfangen werden . Sie können das annehmen max(W, H) <= 2^15 - 1
.
Die Ausgabe
Ihr Programm oder Ihre Funktion sollte eine Liste nicht überlappender verbundener nicht kongruenter pythagoräischer Dreiecke berechnen und eine Liste mit jeweils drei Koordinatensätzen ausgeben, wobei die Koordinaten in einem Satz eines der pythagoräischen Dreiecke bilden, wenn sie durch Linien verbunden sind. Koordinaten müssen in unserem Raum reelle Zahlen sein ( x
müssen im Intervall liegen [0, W]
und y
müssen im Intervall liegen [0, H]
), und der Abstand muss maschinengenau sein. Die Reihenfolge der Dreiecke und das genaue Format jeder Koordinate ist nicht wichtig.
Es muss möglich sein, von einem Dreieck zu einem anderen zu "gehen", indem nur verbundene Grenzen überschritten werden.
Unter Verwendung des obigen Diagramm als Beispiel nehmen wir unsere eingegeben werden W = 60
, H = 60
.
Unsere Ausgabe könnte dann die folgende Liste von Koordinaten sein:
(0, 15), (0, 21), (8, 15)
(0, 21), (14.4, 40.2), (8, 15)
(0, 15), (8, 0), (8, 15)
(8, 0), (8, 15), (28, 15)
(8, 15), (28, 15), (28, 36)
(28, 15), (28, 36), (56, 36)
Nun, 6 Dreiecke sind sicherlich nicht das Beste, was wir in Anbetracht unseres Platzes tun können. Kannst du es besser machen?
Regeln und Wertung
Ihre Punktzahl für diese Herausforderung ist die Anzahl der Dreiecke, die Ihr Programm aufgrund der Eingabe von generiert
W = 1000, H = 1000
. Ich behalte mir das Recht vor, diese Eingabe zu ändern, wenn ich den Verdacht habe, dass jemand diesen Fall fest codiert.Sie dürfen keine eingebauten Funktionen verwenden, die pythagoreische Tripel berechnen, und Sie dürfen keine Liste von mehr als 2 pythagoreischen Tripeln fest codieren (wenn Sie Ihr Programm fest codieren, um immer mit einem (3, 4, 5) Dreieck oder einem ähnlichen Ausgangsumstand zu beginnen) es ist okay).
Sie können Ihren Beitrag in jeder Sprache verfassen. Lesbarkeit und Kommentierung sind erwünscht.
Eine Liste pythagoreischer Tripel finden Sie hier .
Standard-Regelungslücken sind nicht zulässig.
quelle
Antworten:
Python 3, 109
Dies war sicherlich eine täuschend schwere Herausforderung. Es gab viele Male das Schreiben des Codes, bei denen ich meine grundlegenden Geometriefähigkeiten in Frage stellte. Trotzdem bin ich ziemlich zufrieden mit dem Ergebnis. Ich habe mir keine Mühe gegeben, einen komplexen Algorithmus zum Platzieren der Dreiecke zu entwickeln, und stattdessen ist mein Code nur durch das Platzieren des kleinsten Fehlers fehlerhaft, den er finden kann. Ich hoffe, dass ich dies später verbessern kann, oder meine Antwort wird andere davon abhalten, einen besseren Algorithmus zu finden! Alles in allem ein sehr lustiges Problem und es entstehen einige interessante Bilder.
Hier ist der Code:
Hier ist ein Diagramm der Ausgabe für
W = 1000
undH = 1000
mit 109 Dreiecken:Hier ist
W = 10000
undH = 10000
mit 724 Dreiecken:Rufen Sie die
matplotlib_graph()
Funktion nachbuild_all_triangles()
auf, um die Dreiecke grafisch darzustellen.Ich denke, der Code läuft einigermaßen schnell: bei
W = 1000
undH = 1000
es dauert 0,66 Sekunden und beiW = 10000
undH = 10000
es dauert 45 Sekunden mit meinem beschissenen Laptop.quelle
C ++, 146 Dreiecke (Teil 1/2)
Ergebnis als Bild
Algorithmus Beschreibung
Dies verwendet eine Breitensuche des Lösungsraums. In jedem Schritt werden alle eindeutigen Konfigurationen von
k
Dreiecken erstellt, die in die Box passen, und alle eindeutigen Konfigurationen vonk + 1
Dreiecken erstellt, indem alle Optionen zum Hinzufügen eines nicht verwendeten Dreiecks zu einer der Konfigurationen aufgelistet werden.Der Algorithmus ist grundsätzlich so eingestellt, dass er das absolute Maximum mit einem erschöpfenden BFS ermittelt. Und das erfolgreich für kleinere Größen. Beispielsweise wird für eine Box mit 50 x 50 das Maximum in etwa 1 Minute ermittelt. Für 1000x1000 ist der Lösungsraum jedoch viel zu groß. Damit es beendet werden kann, schneide ich die Liste der Lösungen nach jedem Schritt ab. Die Anzahl der Lösungen, die beibehalten werden, wird durch ein Befehlszeilenargument angegeben. Für die obige Lösung wurde ein Wert von 50 verwendet. Dies führte zu einer Laufzeit von ca. 10 Minuten.
Der Umriss der Hauptschritte sieht folgendermaßen aus:
Ein kritischer Aspekt des gesamten Schemas ist, dass Konfigurationen im Allgemeinen mehrmals generiert werden und wir nur an eindeutigen Konfigurationen interessiert sind. Wir brauchen also einen eindeutigen Schlüssel, der eine Lösung definiert, die unabhängig von der Reihenfolge der Dreiecke sein muss, die beim Generieren der Lösung verwendet werden. Zum Beispiel würde die Verwendung von Koordinaten für den Schlüssel überhaupt nicht funktionieren, da sie völlig unterschiedlich sein können, wenn wir in mehreren Aufträgen zu derselben Lösung gelangen. Was ich verwendet habe, ist die Menge der Dreiecksindizes in der globalen Liste sowie eine Menge von "Verbinder" -Objekten, die definieren, wie die Dreiecke verbunden sind. Der Schlüssel codiert also nur die Topologie, unabhängig von der Konstruktionsreihenfolge und Position im 2D-Raum.
Während dies eher ein Implementierungsaspekt ist, entscheidet ein anderer Teil, der nicht ganz trivial ist, ob und wie das Ganze in die vorgegebene Box passt. Wenn Sie die Grenzen wirklich verschieben möchten, ist es offensichtlich erforderlich, dass die Drehung in die Box passt.
Ich werde versuchen, später einige Kommentare zum Code in Teil 2 hinzuzufügen, falls jemand die Details zur Funktionsweise dieses Vorgangs genauer untersuchen möchte.
Ergebnis im offiziellen Textformat
Code
Siehe Teil 2 für den Code. Dies wurde in zwei Teile aufgeteilt, um die Größenbeschränkungen der Pfosten zu umgehen.
Der Code ist auch in PasteBin verfügbar .
quelle
C ++, 146 Dreiecke (Teil 2/2)
Fortsetzung von Teil 1. Dies wurde in zwei Teile aufgeteilt, um die Post-Größenbeschränkungen zu umgehen.
Code
Kommentare hinzugefügt werden.
quelle