极坐标图上行进的两点之间的距离


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
@Peter Taylor,因为它们并非完全相同。以类似的方式,当步长趋于零时,通过在x和y方向上交替的小步长在xy平面上从0,0到1,1的路径看起来与直接对角线路径相同。但是对角线路径的长度为sqrt(2),而阶梯路径的长度始终为
2。– Penguino

1
我认为,如果图像不那么大,挑战看起来会更好。目前,他们很难遵循该文本
Luis Mendo

Answers:


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
Zgarb '16

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<

输入是两个复数的数组。

在线尝试!验证所有测试用例

说明

|       % 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

Ruby,64个字节

首先,我的意见。带参数的Lambda函数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,但使用标识(s-r).abs= s+r-[s,r].min*2将代码缩短2个字节,因此-2放在方括号内。

另一个值得注意的功能是?i.to_c.arg*4不使用的表达式= 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

Python 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. 如果没有添加前2个项目,则为空字符串(''),在Python中显然是一个字符串大于任何整数;
  4. 以及从两个点之间沿圆和射线的传播距离得出的2个最终值,反之亦然。

为什么不math.pi呢?
user202729 '18

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.