救救我,我迷失在海洋中!


11

介绍

今天我独自乘独木舟去钓鱼,不幸的是我睡着了,溪流把我带走了,我失去了桨,现在是晚上,我迷失在大海中!我看不到海岸,所以我必须很远!

我有手机,但由于被咸水弄湿而出现故障,由于麦克风和电话扬声器坏了,所以我无法讲话或听到任何声音,但是我可以向沿海海滩上的朋友发送短信!

我的朋友有一个非常强大的手电筒,他把它举在竹bamboo上,向我展示正确的方向,但是由于我没有桨,所以我不能划船,所以我必须告诉他我有多远,这样他就可以派人去抓住我!

我的朋友告诉我,他将手电筒保持在海平面11.50米处,我可以看到地平线上的光。现在,我只从学校里记得地球半径在海平面应为6371 Km,而且我坐在独木舟中,因此您可以假设我的眼睛也在海平面上。

任务

由于潮流使我时时刻刻在移动,我的朋友不时地举起火炬(现在是12.30米),请编写完整的程序或函数,以帮助我计算与朋友的位置之间的距离!

这是一个图(不按比例):

在此处输入图片说明

标记M为我的橙色点,标记T为火炬的红色点。绿线是M和之间的线性距离T

输入值

从标准输入中获取h在海平面以米为单位的火炬高度,我在地平线上以浮点数的形式显示该浮点数,精度为小数点后两位(精度为1厘米或0.01米)。范围从0到100。

输出量

您应该以1 cm的精度返回绿线的欧几里得长度。例如,如果以米为单位输出,则应至少使用两个小数。输出可以是米或公里,但要注意精度。

测试用例:

所有值以米为单位。

11.5 > 12105.08
13.8 > 13260.45

规则

最短的代码获胜。


结果必须在数学上正确无误还是如果前两位小数正确就可以吗?我的意思是,与2xRxh相比,hxh较小,并且在短距离内可以忽略不计。(R是地球的半径,h是火炬的高度)。
2016年

如果以米为单位输出,@ ss可以使用前两个小数点就可以了
Mario

输入范围是多少?
2016年

@可以,您可以认为输入范围是0到100(在这种情况下,甚至超出了必要/可能的范围)。
马里奥

1
您应该已经尝试过海岸警卫队的堆栈交换-高尔夫球手代码无法帮助您摆脱困境,伙计!
corsiKa

Answers:


4

05AB1E13 12 10字节

感谢Emigna,节省了2个字节。

由于没有使用OP假设地球局部为平面的函数调用三角函数的方法,因此有可能提出05AB1E解决方案。

•1#oC•+¹*t

           For understanding purposes input is referred to as 'h'
•1#oC•     Push 12742000 [ = 2*R, where R is the radius of earth]
      +    Compute 2*R+h
       ¹*  Multiply by h. Result is (2*R*+h)*h
         t Take the square root of it and implicitly display it

在线尝试!


1
12742000可以写成•1#oC•
Emigna '16

作为参考,它应该是9个字节:•1#oC•+*t2sable中
Emigna

用环绕的字符串是否表示一个...底数为214的数字?05AB1E有时缺少有关此类特殊功能的文档。尼斯2sable答案也。几天前我发现了它,但是我没有考虑将其用于此问题。
2016年

正确。它是一个以10为底的214编码数字
。– Emigna

该结果也可以通过三角法获得,但可能更长。
马里奥

4

Python,34 26个字节:

-8字节归功于Osable!

lambda i:(i*(i+12742))**.5

匿名lambda函数。以公里为单位输入,以公里为单位输出。调用为print(<Function Name>(<Input>))


lambda i:(i*(i+12742))**.5会更短。
2016年

@好听的尼斯!我正要这样做。:)
R. Kap

如果存在数学公差,则考虑到i和12742 之间的差异,可以将该表达式缩短:(i*12742)**.5
2013年

结果是错误的。11.5m->〜380km,而不是〜12km
GB

@GB程序将其输入读取为公里。
2016年

4

PHP,34字节

<?=sqrt((12742e3+$h=$argv[1])*$h);

分解

   r^2+x^2=(r+h)^2      # Pythagoras base
   r^2+x^2=r^2+2rh+h^2  # right term distributed
       x^2=    2rh+h^2  # -r^2
       x =sqrt(2rh+h^2) # sqrt

到目前为止,这与旧的Mathematica答案相同

sqrt(2*6371e3*$h+$h*$h) # to PHP
sqrt(14742e3*$h+$h+$h)  # constants combined
sqrt((14742e3+$h)*$h)   # conjugation to save a byte
((14742e3+$h)*$h)**.5   # same size

现在剩下要做的就是添加输入=$argv[1]和输出<?=-完成


4

dc,16 11个字节:

?d12742+*vp

提示通过命令行输入(以公里为单位),然后输出距离(以公里为单位)。

说明

?           # Prompt for input
 d          # Duplicate the top-of-stack value
  12742     # Push 12,742 onto the stack
       +    # Pop the top 2 values of the stack and push their sum
        *   # Pop top 2 values of the stack and push their product
         v  # Pop the remaining value and push the square root
          p # Output the result to STDOUT

这利用了以下优势:

((6371+h)**2-6371**2)**.5 
=> ((6371**2+12742h+h**2)-6371**2)**0.5 
=> (h**2+12742h)**0.5 
=> (h*(h+12742))**0.5

4

jq,18个字符

(12742e3+.)*.|sqrt

相同公式的另一个副本。

样品运行:

bash-4.3$ jq '(12742e3+.)*.|sqrt' <<< 11.5
12105.087040166212

在线测试


4

Haskell,22个字节

d h=sqrt$h*(h+12742e3)

用法:

Prelude> d 11.5
12105.087040166212

无点:(23个字节)

sqrt.((*)=<<(+12742e3))

3

R,29个字节

h=scan();sqrt(h^2+2*h*6371e3)

接受来自stdin的输入


短了两个字节(h=scan())*(1+12742e3/h)^.5
Flounderer

2

Mathematica,16个字节

这些输入和输出中的任何一项都以公里为单位:

(12742#+#*#)^.5&
((12742+#)#)^.5&

这是毕达哥拉斯对问题的简单应用:

   x*x + R*R = (R+h)*(R+h)
=> x*x = (R+h)*(R+h) - R*R
       = R*R + 2*R*h + h*h - R*R
       = 2*R*h + h*h
=>   x = √(2*R*h + h*h)

2

果冻,果冻代码页中的9个字节

我决定尝试用高尔夫球语言编写程序。实际上,我发现一种比其他人使用的算法更有效的算法(至少在短距离内像问题中的算法一样),但是它需要文字浮点数,而Jelly似乎无法对其进行压缩,因此毕达哥拉斯它是。

+“Ȯịż’×µ½

说明:

 “Ȯịż’     12742000, compressed base-250
+          add to argument
      ×    multiply with original argument
       µ   separator to avoid what would otherwise be a parsing ambiguity
        ½  square root everything seen so far
           implicit output at EOF

需要 µ分隔符我感到恼火,但我认为这是不可避免的。通过猜测许多命令需要哪些参数,Jelly已经在05AB1E上节省了一个字节,但是在这种情况下,它无法正确猜测到最后,因此我需要给它一个提示。

果冻,果冻代码页中的7个字节

דȮịż’½

正如我在其他答案中所解释的那样,对毕达哥拉斯逼近的级数逼近实际上在问题中包含的长度上产生了更好的结果(至少,它们更接近示例输出),并且公式也更短。当我写它的时候,我意识到不用预先计算12742000的平方根,我可以先将数字乘以12742000,然后同时将它们的平方根相乘。这基本上等同于不带加法运算符的其他公式,因此,可以通过从以前的程序中删除加法运算符来生成它。这节省了两个字节,因为它现在可以明确解析,因此我们不再需要了µ


我决定不使用此优化,因为如果在给定h的范围内看厘米(参见请求的输出),它不会产生相同的值。它还将在05AB1E中节省2个字节。
2016年

通过优化,我得到了12105.081577585506和13260.452480967608的输出;它们非常接近测试用例的输出,并四舍五入。如果没有,我会得到12105.087040166212和13260.459661716106,它们相距较远(后者在厘米中是错误的,四舍五入为13260.46)。如另一个答案中所述,优化恰好比优化的代码更接近正确的值,因为它包含两个相互抵消的错误,而不是没有任何抵消作用的错误。

由于您刚刚在审核队列中投票赞成“保持开放”,因此我认为您认为您知道我在评论中要求澄清的问题的答案。因此,请编辑问题,使其明确。
彼得·泰勒

1
问题是明确的:作者需要知道与朋友的距离以帮助导航。他可以将割炬的位置确定为精度为0.1米(我们可以从所讲的故事中确定)。在当前距离下,这不可避免地会给输出带来约1米的不确定性(请注意:作者在四处漂移,因此不太可能很快地移动到很远……),因此,任何近似于此的精度都可能是可以接受的。问题的一部分是确定在这种情况下您需要达到的精度!

1
请求的输出以米为单位显示2个小数。因此,精度预计为1厘米。在对问题的评论中,OP表示h可以增加到100。如果h = 100,则与原始算法有14厘米的差异。
2016年

2

红宝石,23岁

23个字节,以Km为单位

->h{(h*h+h*12742)**0.5}

25个字节,以米为单位

->h{(h*h+h*12742e3)**0.5}

1

Tcl,49个字节:

set A [get stdin];puts [expr ($A*($A+12742))**.5]

好吧,我是Tcl的新手,因此非常感谢您打高尔夫球。像我的其他答案一样,提示输入命令行(以千米为单位)和输出(以千米为单位)。从本质上讲,是我现有dcpython答案的Tcl改编版。


s上缺少s
sergiol

1

x86_64 + SSE机器码,16个字节

程序的字节在左边(十六进制),在右边有一个反汇编,使它易于阅读。这是一个遵循常规x86_64约定的函数,该约定用于接受和返回单精度浮点数的函数(它在%xmm0中接受参数,并在同一寄存器中返回其答案,并使用%xmm1和%eax作为临时变量;这些C程序将使用相同的调用约定,因此您可以直接从C程序调用函数(这是我对其进行测试的方式)。

b8 80 19 5f 45          mov    $0x455f1980,%eax
66 0f 6e c8             movd   %eax,%xmm1
0f 51 c0                sqrtps %xmm0,%xmm0
0f 59 c1                mulps  %xmm1,%xmm0
c3                      retq

即使拆卸了,这仍然需要解释。首先,值得讨论公式。大多数人都忽略了地球的曲率,并使用毕达哥拉斯的公式来测量距离。我也正在做,但是我使用的是级数展开逼近。我仅采用与输入的第一幂有关的术语,而忽略了第三,第五,第七等幂,它们在短距离内都只具有很小的影响。(此外,毕达哥拉斯逼近的值较低,而级数展开中的后面项则减小了该值;因此,通过忽略将推向错误方向的逼近的次要因素,我实际上碰巧得到了通过使用不太准确的公式可以得到更准确的结果。)公式的结果为√12742000×√h;0x455f1980

接下来可能使人困惑的是为什么我对平方根和乘法使用向量指令;%xmm0并且%xmm1每个可以容纳四个单精度浮点数,而我正在对这四个进行运算。这里的推理非常简单:它们的编码比相应的标量指令的编码短一字节。因此,我可以使FPU进行大量额外的工作,以便将自己平方根并乘以零,以便为自己节省两个字节,这种方法与典型的高尔夫语言算法非常相似。(我曾将x86汇编程序称为汇编程序的高尔夫语言,前不久在聊天中,但我仍然没有改变主意。)

从那里开始,该算法非常简单:%xmm1通过√12742000进行加载%eax(字节数比从内存加载的字节数短),对参数取平方根(以及三个零),对%xmm1和的对应元素相乘%xmm0(我们只关心关于第一个元素),然后返回。


1

Minkolang v0.15,22个字节

ndd*$r'12742000'*+1MN.

在线尝试!

n                               gets input in the form of a number
 dd                             duplicates it twice
   *                            multiplies 2 of the duplicates with each other
                                STACK: [h, h*h]
    $r                          swap top two stack values
                                STACK: [h*h, h]
      '12742000'*               push this number and multiply the original input by it
                                STACK: [h*h, h*12742000]
                 +1M            adds the two values and takes their square root
                                STACK: [sqrt(h*h+h*12742000)]
                    N.          output as a number and end program

1

JavaScript(ES6),31个 25字节

以米为单位显示值

//the actual code 
f=h=>(h*h+12742e3*h)**0.5


console.log(f(11.5));
console.log(f(13.8));

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.