Comme un segment de chemin; touché pour la première fois

14

Étant donné une liste ordonnée de 2 points cartésiens 2D ou plus, affichez une valeur vraie si le chemin se touche ou s'auto-intersecte; sinon, émettez une valeur falsifiée si elle ne se touche pas ou ne s'auto-intersecte pas.

Vous pouvez supposer que les points consécutifs de la liste sont distincts.

Exemples:

(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

Notez que toutes les coordonnées que j'ai données ici sont des entiers. Vous pouvez prendre en charge les entrées coordonnées de tout ce que vous voulez parmi {entier, décimal, rationnel, virgule flottante, ...}. Mais vos calculs d'implémentation doivent donner les bonnes réponses pour toutes les entrées données.

Traumatisme numérique
la source
4
quel bon titre A +
undergroundmonorail
Scène initiale de Reservoir Dogs , n'importe qui?
Luis Mendo
Pardonnez-moi si je ne comprends pas bien, mais comment le dernier scénario de test ne se recoupe-t-il pas? i.imgur.com/wiNMByd.png
2017
2
@icrieverytim Ce n'est pas une promenade fermée. Le dernier point ne se connecte pas au premier.
HyperNeutrino

Réponses:

5

Python 2 , 315 309 298 382 380 372 octets

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]])

Essayez-le en ligne!

Utilise l'algorithme d' ici , combiné avec cette réponse SO pour les segments colinéaires.

Modifier: corrigé pour les segments de ligne continuant dans la même direction (par exemple (0,0),(1,0),(2,0)) en supprimant le point central, (résultant en (0,0),(2,0)).

TFeld
la source
Vous pouvez enregistrer deux octets en remplaçant les deux occurrences de deux espaces par un seul onglet.
Jonathan Frech
*((n*N>0)+(m*M>0)<1)-> *(n*N<=0>=m*M).
Jonathan Frech
3

Eukleides , 154 148 octets

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

Fonction nommée iqui, a passé un ensemble de points, renvoie 0 ou 1. Les points-virgules et les sauts de ligne sont interchangeables pour terminer une commande, je viens de regrouper quelques éléments pour garder le code visiblement court car nous ne sommes pas habitués à la lisibilité code ici de toute façon.

Eukleides est un langage de géométrie plane principalement pour la sortie graphique, mais aussi avec des capacités programmatiques décentes. Je pensais que ce serait génial pour cette tâche, mais quelques choses m'ont frustré. Tout d'abord, il convient de noter que les ensembles à Eukleides sont essentiellement des tableaux de points et, le cas échéant, sont rendus sous forme de chemins constitués de segments de ligne connectés. Eukleides prend en charge la génération itérative d'ensembles via des loci, semblable à une boucle for qui crée un ensemble dans le processus. Si j'avais pu utiliser un locus, cela aurait réduit les octets, mais apparemment Eukleides n'aime pas référencer un locus partiellement formé de l'intérieur.

L'autre grande frustration était que si, apparemment, deux segments de ligne identiques sont l'un sur l'autre, intersectionne renvoie qu'un seul point incriminé (ce qui est logique, je suppose, il y aurait des intersections infinies). Ma méthode consiste essentiellement à construire le chemin un pas en arrière et à tester le prochain segment de ligne pour les intersections avec le chemin. En raison du comportement d'intersection susmentionné, je vérifie séparément si le point se trouve ou non sur le chemin.

Modifier : Coupez 1 octet en réorganisant l' orinstruction pour permettre la suppression d'un espace avant or; 5 octets de plus en changeant ce ifbloc en opération ternaire.

Cas de test:

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
la source