서클 교차로에서 배타적 영역 찾기


17

당신을 위해 기만적으로 도전하는 지오메트리 퍼즐이 있습니다!

원 A과 n다른 원 이 있다면 그 B[n]안에 포함 된 총 면적 A이 원 안에 있지 않습니다B .

코드는 가능한 짧아야합니다.

입력

입력 내용에는 다음 정보가 포함되어야합니다.

  • 부동 소수점 숫자는 원의 반경을 나타내는 A.
  • 의 반지름을 나타내는 부동 소수점 숫자의 목록입니다 B.
  • 의 원 중심 목록입니다 B. 프로그램은 중심이 극좌표 또는 데카르트 좌표를 기대할 수 있습니다.
  • 선택적 n으로 B로 원 의 수 를 받을 수 있습니다 . 이 입력은 필요하지 않습니다.

원의 중심이 A원점, 즉 점 이라고 가정합니다 (0, 0).

두 원 B이 동일하다는 보장 은 없지만 모든 B교차 원 A, 중심이 B모두 바깥 A에 있거나 두 원이 B서로 교차 하지는 않습니다 . 솔루션이 다양한 에지 케이스를 처리 할 수 ​​있는지 확인하십시오.

어떤 순서로든 텍스트 입력 형식 (stdin 또는 해당 언어를 통해), 함수 매개 변수 또는 명령 줄 인수로 입력을받을 수 있습니다.

텍스트 입력을 받도록 선택한 경우 입력 사이에 하나 또는 두 개의 문자로 인쇄 가능한 ASCII 구분자가 있어야합니다.

산출

프로그램 또는 함수는 A의 원 안에 포함되지 않은 총 면적을 나타내는 단일 부동 소수점 숫자를 출력해야합니다 B. 귀하의 답변은 모든 테스트 사례에 대해 적어도 세 개의 유효 숫자로 정확해야합니다.

일반적인 규칙이 적용됩니다.

면적을 결정하기 위해 원 안의 샘플링 지점에 의존해서는 안됩니다.

원의 교차점을 자동으로 찾거나 원의 교차점에서 영역을 찾거나이 문제를 즉시 해결하는 내장 기능은 허용되지 않습니다.

테스트 사례

각 이미지에서 원 A은 파란색으로, 원 B은 녹색으로 채워지고 검은 색으로 채워집니다. 반환해야 할 영역이 빨간색으로 채워집니다.

( 내 솔루션을 확인한 Rainer P. 에게 감사드립니다 )

테스트 사례 1 :

A = {x: 0, y: 0, rad: 50}
B[0] = {x: 0, y: 0, rad: 100}

테스트 사례 1

Result: 0.00

테스트 사례 2 :

A = {x: 0, y: 0, rad: 100.000000}
B[0] = {x: 100.000000, y: 0.000000, rad: 50.000000}
B[1] = {x: 30.901699, y: -95.105652, rad: 50.000000}
B[2] = {x: -80.901699, y: -58.778525, rad: 50.000000}
B[3] = {x: -80.901699, y: 58.778525, rad: 50.000000}
B[4] = {x: 30.901699, y: 95.105652, rad: 50.000000}

테스트 사례 2

Result: 1.3878e+04

테스트 사례 3 :

A = {x: 0, y: 0, rad: 138}
B[0] = {x: 100, y: 0, rad: 100}
B[1] = {x: -50, y: -86, rad: 100} 
B[2] = {x: -93, y: 135, rad: 50}

테스트 사례 3

Result: 1.8969e+04

테스트 사례 4 :

A = {x: 0, y: 0, rad: 121.593585}
B[0] = {x: 81.000000, y: 107.000000, rad: 59.841457}
B[1] = {x: -152.000000, y: -147.000000, rad: 50.000000}
B[2] = {x: 43.000000, y: -127.000000, rad: 105.118980}
B[3] = {x: 0.000000, y: -72.000000, rad: 57.870545}
B[4] = {x: -97.000000, y: -81.000000, rad: 98.488578}
B[5] = {x: -72.000000, y: 116.000000, rad: 66.468037}
B[6] = {x: 2.000000, y: 51.000000, rad: 50.000000}

테스트 사례 4

Result: 1.1264e+04

테스트 사례 5 :

A = {x: 0, y: 0, rad: 121.605921}
B[0] = {x: 0.000000, y: -293.000000, rad: 250.000000}
B[1] = {x: 0.000000, y: -56.000000, rad: 78.230429}
B[2] = {x: 0.000000, y: -102.000000, rad: 100.000000}

테스트 사례 5

Result: 2.6742e+04

제안 된 독서 :

Fewell, MP "세 원의 공통 중첩 영역." 2006 년 10 월. 웹. http://dspace.dsto.defence.gov.au/dspace/bitstream/1947/4551/4/DSTO-TN-0722.PR.pdf .


나는 2 년 전에이 문제를 해결 하는 동안 두 서클에 대한 문제가 얼마나 간단한 지에 따라이 문제를 직접 해결하려고했습니다 . 나는 당신이 연결 한 논문을 읽게되었고 ... 몬테 카를로와 함께 가기로 결정했습니다. "솔루션이 영역을 결정하기 위해 원 안의 샘플링 지점에 의존해서는 안됩니다." D :
— Martin Ender

한 서클에 B다른 서클이 포함 된 테스트 사례가없는 것 같습니다 . 그것을 추가 할 가치가있을 수 있습니다.
— Martin Ender 2018 년

세 번째 테스트 사례를 확인할 수 있습니까? 을 받고 1.8970e+04있습니다.
— LegionMammal978

@ MartinBüttner 나도 사고로 문제를 겪었습니다. 나는 내 솔루션에 너무 만족하지 않지만 작동하는 것 같습니다. 그 사건에 대해 약간의 시험을 작성하려고 노력할 것입니다, 감사합니다!
— BrainSteel

@ LegionMammal978 예, 잘못 된 것 같습니다. 나는 원 사이의 교차점에 대해 다음 데이터가 : B[0] - A intersection: 20653.659515, B[1] - A intersection: 20757.824115, B[1] - B[0] intersection: 1841.847766, B[2] - A intersection: 1289.164541, 얻을 수있는 18969.69009대답한다.
— BrainSteel

답변:


14

파이썬 2, 631 바이트

from cmath import*
C=input()
O,R=C[0]
def I(p,r,q,s):
 try:q-=p;d=abs(q*q);x=(r*r-s*s+d)/d/2;return[p+q*(x+z*(r*r/d-x*x)**.5)for z in-1j,1j]
 except:return[]
S=sorted
V=S(i.real for p,r in C for c in C for i in[p-r,p+r]+I(p,r,*c)if-R<=(i-O).real<=R)
A=pi*R*R
for l,r in zip(V,V[1:]):
 H=[]
 for p,t in C:
    try:
     for s in-1,1:a,b=[p.imag+s*(t*t-(p.real-x)**2)**.5for x in l,r];H+=[a+b,a,b,s,t,p],
    except:0
 a,b=H[:2];H=S(H[2:]);n=0;c=a
 for d in H:
    s=d[3];z=.5;H*=d<b
    for q,w,e,_,t,y in(c,min(d,b))*(n-s<(a<d)or[0]*n>H):\
g=phase((l+w*1j-y)/(r+e*1j-y));A-=abs(g-sin(g)).real*t*t/2-z*q*(r-l);z=-z
    n-=s
    if(a<d)*s*n==-1:c=d
print A

앞에있는 줄 바꿈 \은 쉽게 읽을 수 있으며 점수에 포함되지 않습니다.

STDIN을 통해 입력을 (center, radius)쌍 목록으로 읽습니다 . 여기서 형식 center은 복소수 X+Yj입니다. 목록의 첫 번째 원은 A (중심이 원점에있을 필요는 없음)이고 나머지 목록은 B 입니다. 결과를 STDOUT에 인쇄합니다.

예

Input:  (0+0j, 138),  (100+0j, 100), (-50+-86j, 100), (-93+135j, 50)
Output: 18969.6900901

설명

이것은 Martin Büttner의 Self-Intercrossting Polygon 과제 영역에 대한 솔루션 에서 (더 길고 훨씬 더 추악한 : P) 변형입니다 . 그것은 문제를 더 작은 조각으로 나누는 것과 같은 트릭을 사용하여 관리하기가 더 쉬워집니다.

우리는 모든 원 쌍 ( A 와 B 의 원을 모두 고려) 사이의 교차점을 찾아 각각을 통해 수직선을 통과시킵니다. 또한 모든 수직선을 접하는 원에 전달합니다. A 와 교차하지 않는 모든 선을 버리고 나머지 모든 선은 A 의 왼쪽과 오른쪽 접선 사이에 있습니다.

그림 1

우리는 A 의 교차 영역 과 B 의 원의 결합 영역을 찾고 있습니다. 위의 그림에서 진한 빨간색 영역입니다. 이것이 결과를 얻기 위해 A 에서 빼야하는 영역입니다 .

연속 된 각 수직선 쌍 사이에서이 영역은 각 다리 옆에 "과도한"호 세그먼트가있는 일련의 수직 사다리꼴 (또는 삼각형, 또는 사다리꼴의 특수한 경우 선 세그먼트)로 나눌 수 있습니다. 우리가 우리만큼 많은 수직선을 통과한다는 사실은 경계 영역이 그보다 더 복잡하지 않다는 것을 보장합니다. 그렇지 않으면 두 선 사이에 추가 교차점이 있어야하고 따라서 수직선이 추가로 있어야하기 때문입니다. 질문.

그림 2

이 사다리꼴과 호 세그먼트를 찾으려면 연속 된 각 수직선 쌍에 대해이 두 선 사이에 올바르게 놓인 각 원의 호 세그먼트를 찾습니다 (물론 일부 원은 주어진 선 쌍 사이에 호 세그먼트가 없을 수 있음) .) 아래 그림에서 두 개의 빨간색 세로선을 고려할 때 6 개의 밝은 황색 선호 세그먼트가 있습니다. 원에 접하는 모든 수직선을 통과하므로 원에 두 선 사이에 호 세그먼트가 있으면 두 선이 반드시 교차하므로 나머지 알고리즘이 단순화됩니다.

이러한 모든 아크가 관련된 것은 아닙니다. 우리는 A 와 B 의 합집합의 경계에있는 것들에만 관심이 있습니다 . 그것들을 찾기 위해 우리는 호를 위에서 아래로 정렬합니다 (호가 서로 교차하지 않을 수 있습니다. 임의의 아크는 다른 아크의 위 또는 아래에 있습니다.)

그림 3

우리 는 현재 내부 에있는 B 개의 원 수를 세면서 n 을 순서대로 호를 가로지 릅니다 . 만약 n은 우리가 내부에있는 동안 0에서 1로 변경 , 또는 우리의 상단 아크에있을 경우 동안 n은 0이 아닌 사다리꼴의 한쪽 다리에 다음 현재 아크 해당합니다. 만약 n 개의 우리 안에있는 동안 1에서 0으로 변경 우리의 바닥 호에 있다면, 또는 동안 N0이 아닌 경우 현재 호는 동일한 사다리꼴의 다른 구간에 해당합니다. 그러한 한 쌍의 호 (위의 그림에서 두 개의 밝은 노란색 호)를 찾으면 해당 사다리꼴 영역과 두 개의 호 세그먼트의 면적을 계산하고 A 에서 뺄 총 면적에 추가합니다 .

사다리꼴 영역뿐만 아니라 A 영역의 계산 은 매우 간단합니다. 각 호 세그먼트의 면적은 해당 원형 섹터의 면적에서 정점이 호 세그먼트의 두 끝점 인 삼각형의 면적에서 해당 원의 중심을 뺀 면적입니다.

그림 4


1
이것은 내가 고려했지만 B에서가 아닌 A에있는 3 자형과 사다리꼴을 찾아서 대상 영역을 직접 찾은 것을 제외하고는 일종의 해결책입니다.이 영역은 삼각형이나 사다리꼴에서 호 세그먼트를 빼서 찾아야합니다.
— quintopia

@quintopia A 의 넓이를 계산할 필요가 없기 때문에 조금 더 짧을 수도 있습니다. 아마도 n 의 조건으로 조금만 연주하면 됩니다.
— ELL

@quintopia OTOH, 당신은 다리 중 하나 옆에 양의 아크가있을 가능성을 설명해야합니다. 만약 그것이 A 의 호 세그먼트 라면 , 누가 알
— 겠습니까

탁월한 솔루션. 이것과 거의 같은 문제가 어제 밤 내 머릿속에 붙어 있었고, 누군가 그것을 해결하기를 정말로 원했습니다. 귀하의 솔루션은 내가 함께 일한 아이디어보다 낫습니다.
— 논리 기사
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.