경로 세그먼트처럼; 처음으로 감동


14

2 개 이상의 2D 데카르트 점으로 정렬 된리스트가 주어지면, 경로가 그 자체에 닿거나 자기 교차 할 경우 진실한 값을 출력합니다. 그렇지 않으면 자체 접촉하지 않거나 자체 교차하지 않으면 잘못된 값을 출력합니다.

목록에서 연속적인 포인트가 다르다고 가정 할 수 있습니다.

예 :

(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

여기에 준 모든 좌표는 정수입니다. {정수, 10 진수, 유리수, 부동 소수점, ...} 중 원하는 항목의 좌표 입력을 지원할 수 있습니다. 그러나 구현 계산은 주어진 입력에 대해 정확한 답을 제공해야합니다.


4
좋은 제목 A +
undergroundmonorail

초기 화면저수지 개 , 누구?
Luis Mendo

내가 오해하는 경우 용서하지만 마지막 테스트 사례는 어떻게 교차하지 않습니까? i.imgur.com/wiNMByd.png
완전 휴먼

2
@icrieverytim 폐쇄 된 산책이 아닙니다. 마지막 지점은 첫 번째 지점에 연결되지 않습니다.
HyperNeutrino

답변:


5

파이썬 (2) , 315 (309) 298 382 380 372 바이트

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

온라인으로 사용해보십시오!

공선 세그먼트에 대해이 SO 답변 과 결합 된 here 의 알고리즘을 사용합니다 .

편집 : (0,0),(1,0),(2,0)중간 점을 제거하여 (같은 결과 ) 같은 방향으로 선 세그먼트가 계속되도록 수정했습니다 (0,0),(2,0).


두 개의 공백을 모두 하나의 탭으로 바꾸면 2 바이트를 절약 할 수 있습니다.
Jonathan Frech

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

3

유클리드 , 154 148 바이트

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

함수 i는 포인트 집합을 통과하고 0 또는 1을 반환합니다. 세미콜론과 줄 바꿈은 명령을 끝내기 위해 서로 바꿔 사용할 수 있습니다. 코드를 읽을 수 없어서 눈에 띄게 짧게 유지하기 위해 몇 가지를 모았습니다. 어쨌든 여기 주위에 코드를 작성하십시오.

Eukleides는 주로 그래픽 출력을위한 평면 지오메트리 언어이지만 적절한 프로그래밍 기능도 있습니다. 나는이 작업에 도움이 될 것이라고 생각했지만 몇 가지가 나를 실망시켰다. 먼저, Eukleides의 세트 는 본질적으로 점의 배열이며 적용 가능한 경우 연결된 선 세그먼트로 이루어진 경로로 렌더링됩니다. Eukleides는 프로세스에서 세트를 생성하는 for-loop와 유사하게 loci를 통해 세트의 반복 생성을 지원합니다. 내가 궤적을 사용할 수 있었다면 바이트를 깎았을 것이지만 Eukleides는 부분적으로 형성된 궤적 자체를 참조하는 것을 좋아하지 않는 것 같습니다.

다른 주요 좌절은 두 개의 동일한 선 세그먼트가 서로 위에 intersection있으면 하나의 문제 지점 만 반환한다는 것입니다 (무한한 교차점이있을 것입니다). 필자의 방법은 본질적으로 한 단계 뒤에 경로를 만들고 경로와의 교차점에 대해 다음 선 세그먼트를 테스트하는 것입니다. 위에서 언급 한 교차 동작으로 인해 포인트가 경로 있는지 여부를 별도로 확인 합니다.

편집 : or전에 공백을 제거 할 수 있도록 명령문을 재정렬하여 1 바이트를 잘라냅니다 or. 해당 if블록을 삼항 연산으로 변경하여 5 바이트 더 .

테스트 사례 :

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.