Wie ein Pfadsegment; Zum aller ersten Mal angefasst

14

Geben Sie bei einer geordneten Liste von 2 oder mehr kartesischen 2D-Punkten einen Wahrheitswert aus, wenn sich der Pfad selbst berührt oder sich selbst schneidet. Andernfalls wird ein falscher Wert ausgegeben, wenn er sich nicht selbst berührt oder sich selbst schneidet.

Sie können davon ausgehen, dass aufeinanderfolgende Punkte in der Liste unterschiedlich sind.

Beispiele:

(0,0), (1,0) -> falsey
(0,0), (1,0), (0,0) -> truthy
(0,0), (1,0), (1,1), (0,0) -> truthy
(0,0), (2,0), (1,1), (1,-1) -> truthy
(0,0), (10,0), (0,1), (10,1), (0,2), (10,2) -> falsey

Beachten Sie, dass alle Koordinaten, die ich hier angegeben habe, Ganzzahlen sind. Möglicherweise unterstützen Sie Koordinateneingaben von beliebigen Werten aus {Ganzzahl, Dezimalzahl, Rational, Gleitkomma, ...}. Aber Ihre Implementierungsberechnungen müssen die richtigen Antworten für alle gegebenen Eingaben geben.

Digitales Trauma
quelle
4
Was für ein guter Titel A +
Undergroundmonorail
Erste Szene mit Reservoir Dogs ?
Luis Mendo
Verzeihen Sie mir, wenn ich falsch verstanden habe, aber wie schneidet sich der letzte Testfall nicht? i.imgur.com/wiNMByd.png
totalhuman
2
@icrieverytim Es ist kein geschlossener Spaziergang. Der letzte Punkt verbindet sich nicht mit dem ersten.
HyperNeutrino

Antworten:

5

Python 2 , 315 309 298 382 380 372 Bytes

s=sorted
w=lambda(x,y),(X,Y),(z,w):(X-x)*(w-y)-(z-x)*(Y-y)
def I(a,b):p,q=s(a);P,Q=s(b);n,N,m,M=w(p,q,P),w(p,q,Q),w(P,Q,p),w(P,Q,q);return(q>=P)*(Q>=p)if{n,N,m,M}=={0}else(b[1]!=a[0])*(n*N<=0>=m*M)
def f(l):
 i=0
 while i<len(l)-2:
	x=l[i:i+3];i+=1
	if w(*x)==0and s(x)==x:l.pop(i);i-=1
 L=zip(l,l[1:]);return any(I(*l)for l in[(k,x)for i,k in enumerate(L)for x in L[:i]])

Probieren Sie es online!

Verwendet den Algorithmus von hier , kombiniert mit dieser SO-Antwort für kollineare Segmente.

Bearbeiten: Korrigiert für Liniensegmente, die in die gleiche Richtung verlaufen (z. B. (0,0),(1,0),(2,0)), indem der Mittelpunkt entfernt wird (was zur Folge hat (0,0),(2,0)).

TFeld
quelle
Sie können zwei Bytes sparen, indem Sie alle zwei Vorkommen von zwei Leerzeichen durch eine einzige Registerkarte ersetzen.
Jonathan Frech
*((n*N>0)+(m*M>0)<1)-> *(n*N<=0>=m*M).
Jonathan Frech
3

Eukleides , 154 148 Bytes

number i (set p)
g=card(p);h=g;n=0;e=p[0];q=e.e
for d in p
if h<g-1 
q=q.e
n=card(intersection(d.e,q))>1or d on q?1|n
end
e=d;h=h-1
end;return n;end

Die Funktion mit dem Namen ithat hat eine Reihe von Punkten übergeben und gibt 0 oder 1 zurück. Semikolons und Zeilenumbrüche sind zum Beenden eines Befehls austauschbar. Ich habe nur ein paar Dinge zusammengefasst, um den Code sichtbar kurz zu halten, da wir nicht an Lesbarkeit gewöhnt sind Code hier sowieso herum.

Eukleides ist eine ebene Geometriesprache, die hauptsächlich für die grafische Ausgabe gedacht ist, aber auch über gute programmatische Fähigkeiten verfügt. Ich dachte, es wäre großartig für diese Aufgabe, aber ein paar Dinge frustrierten mich. Zunächst ist anzumerken, dass Mengen in Eukleides im Wesentlichen Arrays von Punkten sind und gegebenenfalls als Pfade aus verbundenen Liniensegmenten wiedergegeben werden. Eukleides unterstützt die iterative Erzeugung von Mengen über loci, ähnlich einer for-Schleife, die dabei eine Menge erzeugt. Wäre es mir möglich gewesen, einen Locus zu verwenden, hätte er die Anzahl der Bytes verringert, aber anscheinend möchte Eukleides nicht von sich aus auf einen teilweise geformten Locus verweisen.

Die andere große Enttäuschung war, dass, wenn anscheinend zwei identische Liniensegmente übereinander liegen, intersectionnur ein beleidigender Punkt zurückgegeben wird (was, ich nehme an, Sinn macht, dass es unendlich viele Schnittpunkte geben würde). Meine Methode besteht im Wesentlichen darin, den Pfad einen Schritt hinter sich aufzubauen und das nächste Liniensegment auf Schnittpunkte mit dem Pfad zu testen. Aufgrund des oben genannten Kreuzungsverhaltens überprüfe ich separat, ob sich der Punkt auf dem Weg befindet oder nicht .

Bearbeiten : Schneiden Sie 1 Byte ab, indem Sie die orAnweisung neu anordnen , damit zuvor ein Leerzeichen entfernt werden kann or. 5 weitere Bytes durch Ändern dieses ifBlocks in eine ternäre Operation.

Testfälle:

ta=point(0,0).point(1,0)
tb=point(0,0).point(1,0).point(0,0)
tc=point(0,0).point(1,0).point(1,1).point(0,0)
td=point(0,0).point(2,0).point(1,1).point(1,-1)
te=point(0,0).point(10,0).point(0,1).point(10,1).point(0,2).point(10,2)
print i(ta);print i(tb);print i(tc);print i(td);print i(te)

0
1
1
1
0
brhfl
quelle