극좌표 그래프에서 이동하는 두 점 사이의 거리


23

간단한 문제 설명

원점에서 나오는 광선과 원점을 중심으로하는 원에서만 두 지점 사이를 이동하는 최소 거리를 찾는 프로그램을 작성하십시오.

전제의 설명

이제 우리가 비행기에 있다고 상상해 봅시다. 그리고이 비행기에서 우리는 특별한 방식으로 만 여행 할 수 있습니다. 우리는 원점에서 나오는 광선을 여행 할 수 있습니다.

우리가 여행 할 수있는 광선

우리는 또한 원을 중심으로 모든 원을 여행 할 수 있습니다

우리가 여행 할 수있는 서클

이제 우리의 목표는이 비행기의 한 지점에서 다른 지점으로 여행하는 것입니다. 그러나 우리는 단순한 유클리드 경로를 따라 이동할 수 없으며, 중심에서 나오는 광선에 점이 닿는 경우에만 가능합니다.

여기에 이미지 설명을 입력하십시오

우리는이 광선이 광선 중 하나에 떨어지기 때문에 여행 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

원점을 중심으로 한 원을 여행 할 수도 있습니다.

여기에 이미지 설명을 입력하십시오

이제 여기 도전이 있습니다 :

우리는 최단 경로에서 한 지점에서 다른 지점으로 이동해야합니다. 종종 이것은 원과 광선을 여행하는 조합입니다.

여기에 이미지 설명을 입력하십시오

그러나 이것은 또한 두 개의 광선으로 이동할 수 있습니다.

여기에 이미지 설명을 입력하십시오

때로는 최소 거리를 이동하는 두 개의 경로가 있습니다.

여기에 이미지 설명을 입력하십시오

문제

당신의 도전은 우리가이 규칙을 따른다면 두 점이 주어지면 그들 사이의 최소 거리를 줄 수있는 프로그램을 작성하는 것입니다. 입력은 직사각형 또는 극좌표 형식으로 제공 될 수 있으며 출력은 사이의 거리 인 하나의 숫자 여야합니다.

테스트 사례

(직사각형 입력)

(1,1) (1,-1) -> ~ 2.22144
(0,0) (1, 1) -> ~ 1.41421
(1,0) (-0.4161 , 0.90929) -> ~ 2
(1,1) (1, 0) -> ~ 1.19961
(1,2) (3, 4) -> ~ 3.16609

테스트 사례가 직사각형 또는 극좌표 형태입니까? 또한 : bewteen
Angs

그것들은 직사각형 형태로되어 있습니다.
Ando Bando

마지막 예가 맞습니까? ~ 3.166을 받고 있습니다
Angs

6
@ 피터 테일러 그들은 같은 경로가 아니기 때문에. 유사한 방식으로, x 및 y 방향으로 교번하는 작은 단계들을 통한 xy 평면상의 0,0 내지 1,1의 경로는 단계 길이가 0 인 경향이 있기 때문에 직접 대각선 경로와 동일하게 보인다. 그러나 대각선 경로의 길이는 sqrt (2)이고 단계 경로의 길이는 항상 2입니다.
Penguino

1
이미지가 너무 크지 않으면 문제가 더 좋아질 것이라고 생각합니다. 현재 그들은 텍스트를 따르기가 어렵습니다
Luis Mendo 10

답변:


5

하스켈, 49 48 바이트

(a!q)c r=min(q+r)$abs(q-r)+acos(cos$a-c)*min q r

용법:

> let rect2polar (x,y)=(atan2 y x, sqrt(x^2+y^2))
> let test c1 c2=let [(a1,r1),(a2,r2)]=rect2polar<$>[c1,c2] in (a1!r1)a2 r2
> test (1,0) (-0.4161, 0.90929)
1.9999342590038496

바이트를 저장 한 @Zgarb에게 감사합니다


(a!q)c r대신 에 정의하여 바이트를 저장할 수 있습니다 d a q c r.
Zgarb

4

자바 스크립트 (ES6), 65 바이트

with(Math)(r,t,s,u,v=acos(cos(t-u)))=>v<2?abs(r-s)+v*min(r,s):r+s

극좌표를 취합니다. 각도를 0에서 π 사이로 줄이기 위해 @Angs의 트릭을 사용합니다. 직사각형 좌표의 경우 다음과 같이 작동합니다.

with(Math)g=(r,t,s,u,v=acos(cos(t-u)))=>v<2?abs(r-s)+v*min(r,s):r+s
with(Math)f=(x,y,v,w)=>g(hypot(y,x),atan2(y,x),hypot(w,v),atan2(y,v))

3

MATL , 22 바이트

|ttsGZ}/X/bX<*|bd|+hX<

입력은 두 개의 복소수로 구성된 배열입니다.

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .

설명

|       % Implicitly input array and take absolute value of its entries
tt      % Duplicate twice
s       % Sum. This is the length of the path that follows the two radii
GZ}     % Push input again and split into the two numbers
/X/     % Divide and compute angle. This gives the difference of the angles
        % of the two points, between -pi and pi
bX<     % Bubble up a copy of the array of radii and compute minimum
*|      % Multiply and take absolute value. This is the arc part of the
        % path that follows one arc and the difference of radii
bd|     % Bubble up a copy of the array of radii and compute absolute
        % difference. This is the other part of the second path
+       % Add. This gives the length of second path
hX<     % Concatenate and take minimum to produce the smallest length.
        % Implicitly display

2

루비, 64 바이트

먼저 내 제출. 인자 람다 함수 distance 1, angle 1, distance 2, angle2.

->r,a,s,b{([d=(b-a).abs,?i.to_c.arg*4-d,2].min-2)*[r,s].min+s+r}

이제 여기에 66 바이트 (할당 제외 f=) 의 두 가지 다른 솔루션과 64 바이트의 실제 제출이 있습니다.

Solution 1:Using include Math, 66 bytes excluding f=
include Math;f=->r,a,s,b{[acos(cos(b-a)),2].min*[r,s].min+(s-r).abs}

Solution 2:Using complex number to define PI instead, 66 bytes excluding f=
f=->r,a,s,b{[d=(b-a).abs,?i.to_c.arg*4-d,2].min*[r,s].min+(s-r).abs}

SUBMISSION AGAIN, 64 bytes excluding f=
f=->r,a,s,b{([d=(b-a).abs,?i.to_c.arg*4-d,2].min-2)*[r,s].min+s+r}

제출은 솔루션 2를 기반으로하지만 identity (s-r).abs= s+r-[s,r].min*2를 사용 하여 코드를 2 바이트 단축하므로 -2괄호 안에 있습니다.

다른 주목할만한 특징 ?i.to_c.arg*4은를 사용하지 않고 expression = 2 * PI include Math입니다. 정밀도가 낮 으면 리터럴로 대체 할 수 있습니다.

솔루션 2는 테스트 프로그램에 주석을 달았습니다.

f=->r,a,s,b{          #r,s are distances, a,b are angles for points 1 and 2 respectively.                       
    [d=(b-a).abs,       #From nearer point we can take arc of length d radians perhaps crossing zero angle to the ray of the further point
    ?i.to_c.arg*4-d,    #or go the other way round which may be shorter (?i.to_c.arg*4 == 2*PI, subtract d from this.)
    2].min*             #or go through the centre if the angle exceeds 2 radians.
  [r,s].min+          #Multiply the radians by the distance of the nearer point from the origin to get the distance travelled. 
  (s-r).abs           #Now add the distance to move along the ray out to the further point.
}

#test cases per question (given as complex numbers, converted to arrays of [distance,angle]+[distance,angle] (+ concatenates.)
#the "splat" operator * converts the array to 4 separate arguments for the function.
p f[*("1+i".to_c.polar + "1-i".to_c.polar)]
p f[*("0".to_c.polar + "1+i".to_c.polar)]
p f[*("1".to_c.polar + "-0.4161+0.90929i".to_c.polar)]
p f[*("1+i".to_c.polar + "1".to_c.polar)]
p f[*("1+2i".to_c.polar + "3+4i".to_c.polar)]

산출

2.221441469079183
1.4142135623730951
1.9999342590038496
1.1996117257705434
3.1660966740274357

2

매스 매 티카 66 바이트

직사각형 좌표를 사용하여 정확한 기호 솔루션을 출력 할 수 있습니다.

Min[If[(m=Min[{p,q}=Norm/@#])>0,m*VectorAngle@@#,0]+Abs[p-q],p+q]&

용법:

%/@{
{{1,1},{1,-1}},
{{0,0},{1,1}},
{{1,0},{-.4161,.90929}},
{{1,1},{1,0}},
{{1,2},{3,4}}
}

수율 : 상징적 결과

N @ % 수율 :

{2.221441469, 1.414213562, 1.999934259, 1.199611726, 3.166096674}


1
맵시 있는! 기호 경로를 사용하는 경우 테스트 사례 {1,0} {-. 4161, .90929}를 {1,0} {cos (2), sin (2)}로 대체 할 수 있습니다.
Ando Bando

1

파이썬 2 164 126 125 132 바이트 :

def A(a,b,c,d,p=3.1415926535):z=abs(a-c);M=lambda f:2*p*f*abs(b-d)/360.0;print min((a==c)*min(a+c,M(a))+(b==d)*z or'',M(a)+z,M(c)+z)

나는 현재 이것을 더 골프로 조사하고 있습니다. 극좌표를 허용합니다. 형식으로 호출해야합니다 A(r1,θ1,r2,θ2). 12유효 숫자 까지 정확한 부동 소수점 값을 출력합니다 .

온라인으로 사용해보십시오! (아이디어)

다음을 포함하는 최대 3 개의 값으로 구성된 배열에서 최소값을 계산하여 STDOUT으로 출력하는 단순하고 간단한 구현입니다.

  1. 두 길이의 합 ( r1+r2) 또는 두 점 iff를 연결하는 호의 길이 중 최소값 r1==r2;
  2. 차이 두 간의 거리 ( abs(r1-r2)) IFF θ1==θ2 (즉, 두 지점이 동일 선상);
  3. 이전의 두 항목 중 어느 것도 추가되지 않으면, ''분명히 파이썬에서 빈 문자열 ( )은 임의의 정수 보다 큽니다 .
  4. 그리고 두 점 사이에서 원과 광선을 따라 이동 한 거리로부터 주어진 2 개의 최종 값.

왜 안돼 math.pi?
user202729

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