Bei dieser Herausforderung erhalten Sie eine Liste mit Punkten. Diese Punkte liegen auf dem Umfang eines imaginären Quadrats . Ihr Ziel ist es:
- Wenn möglich, drucken Sie die Drehung des Quadrats aus. Dies ist ein Wert von [0, 90], wobei 0 ein Quadrat mit vertikalen und horizontalen Linien darstellt. Die Drehung ist in Grad gegen den Uhrzeigersinn anzugeben.
- Wenn die Drehung des Quadrats mehrdeutig ist (z. B. nur 2 Punkte erhalten), drucken Sie "Unbekannt" aus.
- Wenn das Erstellen eines Quadrats aufgrund der Punkte nicht möglich ist, drucken Sie "Impossible" aus.
Die Punkte, die Sie erhalten, sind garantiert einzigartig und in keiner bestimmten Reihenfolge. Sie können jedes Format verwenden, in das Sie die Liste eingeben möchten, aber für meine Beispiele haben meine Punkte das Formatx,y
und durch Leerzeichen getrennt sein. Die Zahlen sind Gleitkommazahlen, und Sie können davon ausgehen, dass sie in einem Bereich liegen, den Ihre Sprache verarbeiten kann. Ihre Ausgabe sollte auf mindestens 3 Dezimalstellen genau sein und davon ausgehen, dass Ihre Sprache Gleitkommazahlen mit perfekter Genauigkeit verarbeitet.
Hier sind einige Testfälle (ich habe die meisten davon zur einfachen Visualisierung mit ganzen Zahlen erstellt, aber Ihr Programm sollte mit Gleitkommawerten umgehen können):
Unbekannte:
0,0
0,0 1,0
0,0 1,0 0,1
0,0 1,0 0,1 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2
Unmöglich:
0,0 1,0 2,0 3,1 4,2
0,0 1,0 2,0 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2
2,0 0,1 2,2 0,3
0,0 2,1 0,2 2,2 -1,1
Möglich (falls nicht angegeben, sollte 0 zurückgegeben werden):
0,0 1,0 2,0
0,0 0.3,0.3 0.6,0.6 (should return 45)
0,0 0.1,0.2 0.2,0.4 (should return appx 63.435 (the real value is arctan(2)))
0,0 0,1 2,1 2,2
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3
Möglicherweise habe ich einige interessante Testfälle verpasst. Wenn ja, kommentieren Sie bitte, um sie hinzuzufügen.
Das ist Code-Golf, also gewinnt der kürzeste Code!
Antworten:
Rev 1: Ruby, 354 Bytes
weiter golfen dank blutorange.
Ruby, 392 Bytes
Der Algorithmus lautet wie folgt:
-Wählen Sie einen beliebigen Punkt (den ersten) und verschieben Sie diesen zum Ursprung (subtrahieren Sie die Koordinaten dieses Punktes von allen Punkten in der Liste.)
-Versuchen Sie alle Umdrehungen des Quadrats um den Ursprung in Schritten von 0,001 Grad um 360 Grad.
- Wenn bei einer bestimmten Drehung alle Punkte über der y-Achse liegen, zeichnen Sie das kleinstmögliche Quadrat um alle Punkte, einschließlich des niedrigsten und des am weitesten links liegenden Punkts.
-Überprüfen Sie, ob alle Punkte am Rand liegen. Dies geschieht mit einer weichen Berechnung, die jeden Punkt nimmt, die quadratischen Abstände von allen Kanten findet und sie miteinander multipliziert. Dies ergibt eher eine gute Übereinstimmung als eine Ja / Nein-Antwort. Es wird interpretiert, dass eine Lösung gefunden wird, wenn dieses Produkt dividiert durch die Seitenlänge ^ 8 kleiner als 1E-9 ist. In der Praxis ist dies weniger als ein Toleranzgrad.
-Die beste Anpassung wird um 90 Grad vorgenommen und als korrekter Winkel angegeben.
Derzeit gibt der Code den Wert mehrdeutig zurück, wenn mehr als 100 Lösungen gefunden werden (bei einer Auflösung von 0,001 Grad. Das sind 0,1 Grad Toleranz.)
erste voll funktionsfähige Funktion im Testprogramm
Ich habe die Auflösung auf 1/10 der erforderlichen Auflösung belassen, um die Geschwindigkeit angemessen zu machen. Im letzten Testfall ist ein Fehler von 0,01 Grad aufgetreten.
Golf-Version, Auflösung gemäß Spezifikation, dauert etwa eine Minute pro Anruf im Testprogramm.
Es gibt immer noch einen lästigen Fehler von 0,001 Grad im letzten Testfall. Eine weitere Erhöhung der Auflösung würde diese wahrscheinlich beseitigen.
Beachten Sie, dass dieser Algorithmus für etwa 30% mehr Code schnell angepasst werden könnte: Es ist offensichtlich, dass in Fällen mit einer begrenzten Anzahl von Lösungen eine der Kanten flach entlang eines Würfels liegt, sodass wir wirklich nur diese Winkel ausprobieren müssen das entspricht jedem Paar von Eckpunkten. Es wäre auch notwendig, ein bisschen zu wackeln, um zu überprüfen, ob es nicht unendlich viele Lösungen gibt.
quelle
0,0 1,0 2,0 1,2
ist noch möglich für ein Quadrat der Diagonale 0,0 ... 2,2. Ich habe das ausprobiert und auch0,0 1,0 2,0 1,1
(letzteres ist in der Tat unmöglich). Ein weiterer Punkt: Halten Sie es für akzeptabel oder inakzeptabel, dass mein Code nicht unbekannt, sondern unmöglich zurückgegeben wird, wenn nur ein einziger Punkt angegeben wird? Ich würde mich über eine Antwort freuen, bevor ich mit dem Golfen beginne.1,1
. Ich bin mir nicht sicher, wie1,2
ich dahin gekommen bin. Es ist nicht akzeptabel.if..end
s verlassen, weil ich schreckliche Probleme mit verschachtelten ternären Operatoren in Ruby habe. Ich sehe, dass Sie das umgehen, indem Sie&&
.Perl
Hallo, hier ist meine bescheidene Rede. Testfälle werden im DATA- Stream am Ende der Datei abgelegt. Der Algorithmus ist durch einen Try-Error-Ansatz gewachsen.
Ich gebe zu, dass es ein allgemein heuristischer Ansatz ist, aber er ist sehr schnell: Er löst alle Fälle sofort .
Ich bin mir bewusst, dass es einige Fehler geben wird, aber bis jetzt werden alle Testfälle korrekt beantwortet.
Mir ist auch bewusst, dass der kürzeste Code gewinnt, aber ich bin mir sicher, dass dieser zu den kürzesten im Internet gehört schnellsten gehört Sinne des Begriffs gehört.
Hier ist der Algorithmus
Punkte untersuchen und für jedes Segment zwischen zwei Punkten Steigung, Länge, x-Achsenabschnitt, y-Achsenabschnitt aufzeichnen
Finde gerade Linien (dh drei Punkte oder zwei benachbarte Segmente) und unterscheide mögliche Steigungen (sprich Rotationen). Verfolgen Sie das längste verfügbare Segment in jeder Zeile.
finden Sie alle Abstände zwischen einem Segment und einem dritten Punkt (dies sollte verwendet werden, um Punkt 4). Verfolgen Sie den Mindestabstand ungleich Null.
für vier beliebige Punkte (ein raues Rechteck) finden Sie innere Punkte
Lösungen anzeigen:
A. Sagen Sie "Unmöglich", wenn es einen oder mehrere innere Punkte gibt.
B. Eine Zeile:
Bei den meisten Punkten in einer einzelnen Zeile ohne innere Punkte sagen Sie "Möglich".
Bei Punkten, die zu nahe an der Linie liegen, sagen Sie "Unmöglich".
C. Zwei Zeilen:
Sagen Sie "Möglich", wenn es nur eine mögliche Drehung gibt
Sagen Sie "Unmöglich", wenn es mehr als eine Umdrehung gibt
D. Keine Linien: Finden Sie eine Drehung, die zu dem um 90 ° gedrehten Segment passt
Sagen Sie "Möglich", wenn nur einer passt oder so viele Punkte passen.
Sagen Sie "Unmöglich", wenn mehr als einer passt und nicht so viele wie Punkte
Sagen Sie "Unbekannt", wenn so viele wie Rotation passen.
Hier ist der Code (alle bekannten Fehler sind behoben)
Und hier ist seine Ausgabe
Grüße.
Matteo.
quelle