Come un segmento di percorso; toccato per la prima volta


14

Dato un elenco ordinato di 2 o più punti cartesiani 2D, genera un valore di verità se il percorso si tocca o si interseca da solo; in caso contrario emette un valore falso se non si tocca da solo o si interseca da solo.

Si può presumere che i punti consecutivi nell'elenco siano distinti.

Esempi:

(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

Nota che tutte le coordinate che ho dato qui sono numeri interi. Puoi supportare input coordinati di qualunque cosa ti piaccia da {numero intero, decimale, razionale, virgola mobile, ...}. Ma i calcoli delle implementazioni devono fornire le risposte corrette per tutti gli input forniti.


4
che bel titolo A +
undergroundmonorail

Scena iniziale di Reservoir Dogs , chiunque?
Luis Mendo,

Scusatemi se non capisco, ma in che modo l'ultimo test non si interseca? i.imgur.com/wiNMByd.png
totalmente umano

2
@icrieverytim Non è una passeggiata chiusa. L'ultimo punto non si collega al primo.
HyperNeutrino,

Risposte:


5

Python 2 , 315 309 298 382 380 372 byte

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

Provalo online!

Utilizza l'algoritmo da qui , combinato con questa risposta SO per segmenti collineari.

Modifica: risolto per i segmenti di linea che proseguivano nella stessa direzione (ad es. (0,0),(1,0),(2,0)) Rimuovendo il punto centrale, (risultante (0,0),(2,0)).


È possibile salvare due byte sostituendo tutte e due le occorrenze di due spazi con una singola scheda.
Jonathan Frech,

*((n*N>0)+(m*M>0)<1)-> *(n*N<=0>=m*M).
Jonathan Frech,

3

Eukleides , 154 148 byte

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

La funzione ha chiamato iquesto, ha passato un set di punti, restituisce 0 o 1. I punti e virgola e le interruzioni di riga sono intercambiabili per la fine di un comando, ho appena raggruppato alcune cose insieme per mantenere il codice visibilmente breve poiché non siamo abituati a leggibili codice qui intorno comunque.

Eukleides è un linguaggio di geometria piana principalmente per l'output grafico, ma anche con capacità programmatiche decenti. Ho pensato che sarebbe stato fantastico per questo compito, ma alcune cose mi hanno frustrato. Innanzitutto, vale la pena notare che gli insiemi in Eukleides sono essenzialmente matrici di punti e, quando applicabile, sono resi come percorsi costituiti da segmenti di linea collegati. Eukleides supporta la generazione iterativa di set tramite loci, simile a un for-loop che crea un set nel processo. Se fossi stato in grado di usare un locus, si sarebbe rasato i byte, ma apparentemente a Eukleides non piace fare riferimento a un locus parzialmente formato dall'interno di se stesso.

L'altra grande frustrazione è che se, a quanto pare, due segmenti di linea identici fossero uno sopra l'altro, intersectionrestituisce solo un punto offensivo (il che ha senso, suppongo, ci sarebbero intersezioni infinite). Il mio metodo è essenzialmente quello di costruire il percorso un passo indietro e testare il segmento di linea successivo per intersezioni con il percorso. A causa del suddetto comportamento di intersezione, controllo separatamente se il punto si trova sul percorso.

Modifica : tagliare 1 byte riordinando l' oristruzione per consentire la rimozione di uno spazio prima or; 5 byte in più modificando quel ifblocco in un'operazione ternaria.

Casi 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.