Seperti segmen jalan; tersentuh untuk pertama kalinya

14

Diberikan daftar 2 titik kartesian 2D atau lebih yang dipesan, menampilkan nilai yang benar jika jalur menyentuh dirinya sendiri atau memotong sendiri; jika tidak, output nilai falsy jika tidak menyentuh sendiri atau berpotongan sendiri.

Anda dapat mengasumsikan bahwa poin berturut-turut dalam daftar berbeda.

Contoh:

(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

Perhatikan bahwa semua koordinat yang saya berikan di sini adalah bilangan bulat. Anda dapat mendukung input koordinat apa pun yang Anda suka dari {integer, desimal, rasional, floating-point, ...}. Tetapi perhitungan implementasi Anda harus memberikan jawaban yang benar untuk setiap input yang diberikan.

Trauma Digital
sumber
4
apa judul yang bagus A +
undergroundmonorail
Adegan awal dari Reservoir Dogs , siapa?
Luis Mendo
Maafkan saya jika saya salah paham, tetapi bagaimana test case terakhir tidak berpotongan? i.imgur.com/wiNMByd.png
totallyhuman
2
@icrieverytim Ini bukan jalan yang tertutup. Poin terakhir tidak terhubung ke yang pertama.
HyperNeutrino

Jawaban:

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

Cobalah online!

Gunakan algoritma dari sini , dikombinasikan dengan jawaban SO ini untuk segmen collinear.

Sunting: Diperbaiki untuk segmen garis yang melanjutkan ke arah yang sama (misalnya (0,0),(1,0),(2,0)) dengan menghapus titik tengah, (menghasilkan (0,0),(2,0)).

TFeld
sumber
Anda dapat menyimpan dua byte dengan mengganti semua dua kemunculan dua spasi dengan satu tab.
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

Nama fungsi i itu, melewati serangkaian titik, mengembalikan 0 atau 1. Tanda titik koma dan jeda baris dapat dipertukarkan untuk mengakhiri perintah, saya hanya menyatukan beberapa hal bersama-sama demi menjaga kode terlihat singkat karena kita tidak terbiasa terbaca kode di sekitar sini pula.

Eukleides adalah bahasa bidang geometri terutama untuk output grafis, tetapi dengan kemampuan pemrograman yang baik juga. Saya pikir itu akan bagus untuk tugas ini, tetapi beberapa hal membuat saya frustrasi. Pertama, perlu dicatat bahwa set pada Eukleides pada dasarnya adalah array poin, dan ketika berlaku diberikan sebagai jalur yang dibuat dari segmen garis yang terhubung. Eukleides mendukung pembuatan iteratif set melalui loci, mirip dengan for-loop yang menciptakan set dalam proses. Seandainya saya bisa menggunakan lokus, itu akan mencukur byte, tetapi tampaknya Eukleides tidak suka merujuk lokus yang terbentuk sebagian dari dalam dirinya sendiri.

Frustrasi besar lainnya adalah bahwa jika, tampaknya, dua segmen garis yang identik berada di atas satu sama lain, intersectionhanya mengembalikan satu titik yang menyinggung (yang masuk akal, saya kira, akan ada persimpangan yang tak terbatas). Metode saya pada dasarnya adalah untuk membangun jalur satu langkah di belakang, dan menguji segmen baris berikutnya untuk persimpangan dengan jalur. Karena perilaku persimpangan tersebut saya periksa secara terpisah apakah titik ada di jalan.

Sunting : Potong 1 byte dengan menyusun kembali orpernyataan untuk memungkinkan penghapusan spasi sebelumnya or; 5 byte lebih banyak dengan mengubah ifblok itu menjadi operasi ternary.

Kasus uji:

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
sumber