Hintergrund
Die konvexe Hülle einer endlichen Anzahl von Punkten ist das kleinste konvexe Polygon, das alle Punkte enthält, entweder als Eckpunkte oder im Inneren. Weitere Informationen finden Sie in dieser Frage zu PGM, die sie sehr gut definiert .
Eingang
N+1
2-D-Koordinaten ( N >= 3
) werden STDIN
im folgenden Format durchlaufen (wobei auch andere übliche Golfeingaben zulässig sind) (die Anzahl der Dezimalstellen kann variieren, Sie können jedoch davon ausgehen, dass sie "angemessen" bleibt und jede Zahl als Float dargestellt werden kann):
0.00;0.00000
1;0.00
0.000;1.0000
-1.00;1.000000
Ausgabe
Ein Wahrheitswert, der gedruckt wird STDOUT
(oder ein Äquivalent), wenn sich der erste Punkt in der Liste ( (0.00;0.00000)
im obigen Beispiel) in der konvexen Hülle der anderen N Punkte befindet, und ansonsten ein Falschwert.
Dies ist Code-Golf , also gewinnt die kürzeste Lösung in Bytes.
Grenzfälle : Sie können einen beliebigen Wert zurückgeben (aber nicht abstürzen), wenn der Punkt am Rand des konvexen Rumpfs liegt (dh auf einer Seite oder auf einem Scheitelpunkt an der Außengrenze des Rumpfes), da dies eine Wahrscheinlichkeit von Null ist Ereignis (unter jeder vernünftigen Wahrscheinlichkeit).
Verboten : alles (Sprache, Operator, Datenstruktur, Integriertes oder Paket), das nur zur Lösung geometrischer Probleme existiert (z. B. Mathematica's ConvexHull ). Allgemeine mathematische Werkzeuge (Vektoren, Matrizen, komplexe Zahlen usw.) sind zulässig.
Tests
- Sollte zurückkehren
TRUE
: spiralTest1-TRUE , squareTest1-TRUE - Sollte zurückkehren
FALSE
: spiralTest2-FALSE , squareTest2-FALSE
sort
oder eliminierenround
. Ich denke, es ist klarer zu sagen, dass nichts, was speziell für die Geometrie gemacht wurde, erlaubt ist. Was ist jedoch mit einer Funktion zum Hinzufügen von zwei Listen als Vektoren? Oder eine Funktion, um das Argument (den Winkel) einer komplexen Zahl zu finden?Antworten:
J,
403934 BytesEine anonyme dyadische Funktion, die einen Punkt p als eines ihrer Argumente und eine Liste von Punkten P als anderes Argument verwendet (es spielt keine Rolle, welches Argument welches ist) und zurückgibt
0
oder1
, wenn p außerhalb von oder liegt innerhalb der konvexen Hülle von P , respectively. Der Punkt p und die Punkte in P werden als komplexe Zahlen genommen.Beispiel
oder...
Python 2, Funktion,
121103, volles Programm,162Python 3, 149 Bytes
Übernimmt die Eingabe im gleichen Format wie der ursprüngliche Beitrag über STDIN und gibt einen booleschen Wert aus, der angibt, ob sich p in der konvexen Hülle von P befindet
Erläuterung
Das Programm testet, ob die Differenz zwischen dem maximalen und dem minimalen (vorzeichenbehafteten) Winkel zwischen einem Punkt r in P , p und einem festen beliebigen Punkt q in P (wir verwenden nur den ersten Punkt in P ) weniger als 180 ° beträgt. Mit anderen Worten wird geprüft, ob alle Punkte in P in einem Winkel von 180 ° oder weniger um p enthalten sind . p befindet sich genau dann in der konvexen Hülle von P, wenn diese Bedingung falsch ist.
Auf Kosten einiger weiterer Bytes können wir eine ähnliche Methode verwenden, bei der wir keine expliziten Winkel berechnen müssen: Beachten Sie, dass die obige Bedingung der Aussage entspricht, dass p genau dann außerhalb der konvexen Hülle von P liegt, wenn es existiert eine Linie l bis p , so dass alle Punkte in P auf derselben Seite von l liegen . Wenn eine solche Linie existiert, gibt es auch eine solche Linie, die auf einen (oder mehrere) der Punkte in P fällt (wir können l drehen, bis sie einen der Punkte in P berührt ).
Um diese Linie (vorläufig) zu finden, lassen wir zunächst l die Linie durch p und den ersten Punkt in P sein . Wir iterieren dann über den Rest der Punkte in P ; Wenn einer der Punkte links von l liegt (wir nehmen durchgehend eine gewisse Richtwirkung an, links oder rechts spielt keine Rolle), ersetzen wir l durch die Linie, die durch p und diesen Punkt verläuft, und fahren fort. Nachdem wir über ganz P iteriert haben , sollten sich alle Punkte in P rechts von (oder auf) l befinden , wenn (und nur wenn) p außerhalb der konvexen Hülle liegt . Wir überprüfen dies mit einem zweiten Durchgang über die Punkte in P..
Python 2, 172 Bytes
Um dasselbe in einem einzigen Durchgang zu tun, sei links von P eine Beziehung zwischen zwei beliebigen Punkten q und r in P , so dass q links von r steht, wenn q links ist der Linie durch p und r . Es ist zu beachten, dass links davon eine Ordnungsbeziehung auf P ist, wenn und nur wenn alle Punkte in P auf derselben Seite einer Linie liegen, die durch p verläuft, dh wenn p außerhalb der konvexen Hülle von P liegt . Das oben beschriebene Verfahren findet den Minimalpunkt in P.wrt diese Ordnung, das heißt, den „ganz links“ Punkt in P . Anstatt zwei Durchgänge durchzuführen, können wir das Maximum (dh den Punkt "ganz rechts") sowie das Minimum der Punkte in P in derselben Reihenfolge in einem einzigen Durchgang ermitteln und sicherstellen, dass das Minimum links vom Punkt liegt Maximum, dh effektiv, dass links davon transitiv ist.
Dies würde gut funktionieren, wenn sich p außerhalb der konvexen Hülle von P befindet. In diesem Fall ist links von tatsächlich eine Ordnungsrelation, kann jedoch brechen, wenn sich p innerhalb der konvexen Hülle befindet (versuchen Sie beispielsweise herauszufinden, was wird passieren, wenn wir diesen Algorithmus ausführen, bei dem die Punkte in P die Eckpunkte eines regulären Fünfecks sind, das gegen den Uhrzeigersinn verläuft, und p sein Zentrum ist.) Um dies zu berücksichtigen, ändern wir den Algorithmus geringfügig: Wir wählen einen Punkt q in P und halbieren P entlang der Linie durch p und q (dh wir teilen P um q auflinks von.) Wir haben jetzt einen "linken Teil" und einen "rechten Teil" von P , die jeweils in einer Halbebene enthalten sind, so dass links von jedem eine Ordnungsrelation auf jedem ist; Wir finden das Minimum des linken Teils und das Maximum des rechten Teils und vergleichen sie wie oben beschrieben. Natürlich müssen wir P nicht physisch halbieren , wir können einfach jeden Punkt in P klassifizieren, während wir in einem einzigen Durchgang nach dem Minimum und Maximum suchen.
Python 2, 194 Bytes
quelle
Oktave,
8272 BytesDie Idee ist zu prüfen, ob das lineare Programm min {c'x: Ax = b, e'x = 1, x> = 0} eine Lösung hat, wobei e ein Vektor aller Einsen ist, Spalten von A die Koordinaten von sind die Punktwolke und b ist der Testpunkt und c ist beliebig. Mit anderen Worten, wir versuchen, b als eine konvexe Kombination von Spalten von A darzustellen.
Verwenden Sie zum Ausführen des Skripts
octave -f script.m <input.dat
quelle
R, 207 Bytes
Das Skript bezieht seine Eingaben von STDIN, z
Rscript script.R < inputFile
.Es generiert alle Dreiecke aus den
N
letzten Punkten (der letzten Linieapply(combn(...
) und prüft mit dert
Funktion , ob sich der erste Punkt im Dreieck befindet .t
verwendet die Bereichsmethode, um zu entscheiden, obU
inABC
: (Schreiben(ABC)
für den Bereich vonABC
)U
inABC
iff(ABC) == (ABU) + (ACU) + (BCU)
. Außerdem werden Flächen nach der Determinantenformel berechnet (siehe hier für eine schöne Demo von Wolfram).Ich vermute, dass diese Lösung anfälliger für numerische Fehler ist als meine andere, aber sie funktioniert in meinen Testfällen.
quelle
R 282 Bytes
Das Skript bezieht seine Eingaben von STDIN, z
Rscript script.R < inputFile
.Es generiert alle Dreiecke aus den
N
letzten Punkten (der letzten Linieapply(combn(...
) und prüft mit dert
Funktion , ob sich der erste Punkt im Dreieck befindet .t
verwendet die baryzentrische Methode, um zu entscheiden, obU
inABC
: (SchreibenXY
für denX
to-Y
Vektor), da dies(AB,AC)
eine Basis für die Ebene ist (mit Ausnahme der entarteten Fälle, in denen A, B, C ausgerichtet sind),AU
alsAU = u.AB + v.AC
undU
im Dreieck iff geschrieben werden kannu > 0 && v > 0 && u+v < 1
. Siehe zum Beispiel hier für eine detailliertere Erklärung und eine schöne interaktive Grafik. NB: Um ein paar Zeichen zu speichern und DIV0-Fehler zu vermeiden, berechnen wir nur eine Verknüpfung zuu
undv
und einen modifizierten Test (min(u*k,v*k,k-u-v)>0
).Die einzigen mathematischen Operatoren verwendet werden
+
,-
,*
,min()>0
.quelle