極座標グラフチャート上を移動する2点間の距離


23

問題の簡単な説明

原点から発せられる光線と原点を中心とする円のみを移動する2点間の最小距離を見つけるプログラムを作成します。

前提の説明

今、私たちが飛行機に乗っていると想像してみましょう。この飛行機では、特別な方法でのみ旅行が許可されています。原点から発せられる光線で移動できます。

旅行できる光線

また、円を中心とした任意の円を旅することができます

旅行できるサークル

今、私たちの目標は、この飛行機のある地点から別の地点に移動することです。ただし、単純なユークリッドパスを移動することはできません。ポイントがたまたま中心から放射される光線に当たる場合にのみ、これを行うことができます。

ここに画像の説明を入力してください

これは私たちの光線の1つに当たるので、この上を移動できます。

ここに画像の説明を入力してください

原点を中心とする円上を移動することもできます。

ここに画像の説明を入力してください

これが課題です。

最短経路である地点から別の地点に到達する必要があります。多くの場合、これは円と光線の移動の組み合わせです。

ここに画像の説明を入力してください

ただし、これは2つの光線で移動することもできます。

ここに画像の説明を入力してください

最小距離を移動する2つのパスが存在する場合があります。

ここに画像の説明を入力してください

問題

あなたの課題は、これらのルールに従えば、2つのポイントが与えられたときにそれらの間の最小距離を与えるプログラムを書くことです。入力は、長方形または極形式のいずれかで指定でき、出力は1つの数値、つまり距離である必要があります。

テストケース

(矩形入力の場合)

(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

それらは長方形の形で、それを明確にする必要があります
安藤坂東

最後の例は正しいですか?私は〜3.166取得しています
Angs

6
@Peter Taylor彼らは実際には同じ道ではないからです。同様に、ステップ長がゼロになる傾向があるため、x方向とy方向に交互する小さなステップを介したxy平面上の0,0から1,1へのパスは、直接の斜めのパスと同じように見えます。ステップパスは常に長さ2がありますしながら、しかし、斜めのパスは、長さSQRT(2)を持っている
Penguino

1
画像がそれほど大きくなければ、課題はより良く見えると思います。現在、彼らはテキストに従うのを難しくしています
ルイス・メンドー

回答:


5

Haskell、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
ズガルブ

4

JavaScript(ES6)、65バイト

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

極座標を取ります。@Angsのトリックを使用して、角度を0〜πに減らします。直交座標の場合、次のように機能します。

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<

入力は2つの複素数の配列です。

オンラインでお試しください!または、すべてのテストケースを確認します

説明

|       % 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=)の2つの異なるソリューションと、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します。したがって、括弧内になります。

もう1つの注目すべき機能は、?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

Mathematica 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. 2つの長さの合計(r1+r2)または2点を接続する円弧の長さのうちの最小値iff r1==r2 ;
  2. 二つの距離の間(abs(r1-r2)IFF θ1==θ2(すなわち、2つの点が同一直線上にあります)。
  3. 前の2つの項目のいずれも追加されない場合、空の文字列('')はPythonで明らかに文字列が整数よりも大きいように;
  4. 円と光線に沿って移動した距離から与えられた2つの最終値、およびその逆の2点。

どうしてmath.pi
user202729

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.