平均角度


15

故事,或者我们为什么要这样做。

没有。除非斯蒂芬霍金(Stephen Hawking),否则这个练习是毫无意义的。

挑战

给定一个角度列表,找到这些角度的平均值。例如,91度和-91度的平均值为180度。您可以使用程序或函数来执行此操作。

输入值

表示角度量度的度值列表。您可以假设它们将是整数。它们可以以任何方便的格式输入或作为函数参数提供。

输出量

输入值的平均值。如果发现平均值有多个,则仅输出一个。平均值定义为

在此处输入图片说明

被最小化。输出必须在(-180,180]范围内,并且至少精确到小数点后两位。

例子:

> 1 3
2
> 90 -90
0 or 180
> 0 -120 120
0 or -120 or 120
> 0 810
45
> 1 3 3
2.33
> 180 60 -60
180 or 60 or -60
> 0 15 45 460
40
> 91 -91
180
> -89 89
0

,字节数最少的提交将获胜。

排行榜

这是一个堆栈片段,用于按语言生成常规排行榜和获胜者概述。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

## Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

## Ruby, <s>104</s> <s>101</s> 96 bytes

如果您想在标头中包含多个数字(例如,因为您的分数是两个文件的总和,或者您想单独列出解释器标志罚分),请确保实际分数是标头中的最后一个数字:

## Perl, 43 + 2 (-p flag) = 45 bytes

您还可以将语言名称设置为链接,然后该链接将显示在页首横幅代码段中:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

这是有关此问题的任何聊天室:http : //chat.stackexchange.com/rooms/30175/room-for-average-of-angles


如果91,-91给出180,90,-90不应该给出180吗?
蓝色

2
直观上,-91和91的平均值为0,而不是180。根据您的定义,我们得到:(180-91)^ 2 +(180- -91)^ 2 => 81362,而(0-91)^ 2 +( 0- -91)^ 2 =>16562。因此180肯定不能是平均值。我在这里想念什么?
edc65

91%360 = 91; -91%360 = 269;(269 + 91)/ 2 = 180。没关系,看错了。也许?我现在不确定。
蓝色

好,谢谢。仍然不知道如何找到它
edc65

3
到目前为止,没有一个测试用例能够打破错误的算法,即简单地将所有角度取为360°,取其平均值,然后如果结果大于180°,则减去360°。您应该添加一个[89°,-89°]之类的情况,该情况应返回0°。
Anders Kaseorg

Answers:


7

Python 3,129个字节

lambda l:min([sum(((b-a)%360)**2for b in l)*len(l)-s*s,180-(180-a-s/len(l))%360]for a in l for s in[sum((b-a)%360for b in l)])[1]

这个问题似乎引起了很多混乱。直观上,该想法是在某个点处切掉角度的圆,将圆解开为一条线,计算该线上的算术平均值,然后将结果重新包装回圆。但是您可以选择在许多不同的地方切圆。仅仅选择一个,例如0°或180°是不够的。您需要全部尝试一下,看看哪一个导致最小的平方距离总和。如果您的解决方案比这简单得多,那可能是错误的。


1
@AndreasKaseorg我认为您可以通过更改s**2s*s
Ioannes

看到我对这个问题的评论。
msh210 '18

@ msh210不确定您为什么要直接向我发表此评论。我的解决方案已经可以这样工作了。
安德斯·卡塞格

这部分是对本答复帖最后一句话的答复。
msh210 '18年

4

Python 3,85个字节

lambda l:180-min(range(72000),key=lambda x:sum((180-(x/200+i)%360)**2for i in l))/200

通过以度为单位尝试所有可能的角度,只需要将答案精确到小数点后两位即可1/200。这在我的机器上花费不到一秒钟。

由于Python不允许我们方便地列出浮点数的算术级数,因此我们将可能的角度表示为整数[0,72000),然后将其转换(-180,180]x -> 180 - x/200。我们发现其中之一给出了最小的平方角差之和。

对于角位移为的两个角,d通过将转换(-180,180]180-(d+180)%360,然后求平方,求出平方角距离。方便地,由给出的角度x/200已经偏移了180度数。


使用增量1/200实际上是有问题的。对于测试用例[1, 3, 3],此解决方案返回2.335并四舍五入为2.34正确答案2.33
乔尔

@Joel我不确定您从何处获取舍入,2.33该示例中的十进制数字似乎正确。无论如何,将200to 400或to 更改为2000(并72000相应地)使其在四舍五入的情况下仍有效吗?另外,再次看这个老问题,我想我可能会发现更好的方法。
xnor19

0.01=一种[RG一世ñXFX[ss+0.01]Fs<Fs+0.01|-s|<|-s+0.01|[RØüñd=sFFs>Fs+0.01Fs=Fs+0.01[RØüñd=s+0.01F

这是一个TIO链接供您测试。
乔尔,

哦,我才意识到你是对的。如果正确答案是,2.333...并且您的程序返回2.335,则它是正确的,直到小数点后两位无舍入。抱歉
乔尔,

3

八度,97 95字节

p=pi;x=p:-1e-5:-p;z=@(L)sum((p-abs(abs(x-mod(L,360)*p/180)-p)).^2);@(L)x(z(L)==min(z(L)))*180/p

这将产生一个匿名函数,该函数仅在足够好的网格上搜索给定函数的最小值。作为输入,函数接受列向量,例如[180; 60; -60]。为了进行测试,您需要给函数命名。因此,您可以例如运行上面的代码,然后使用ans([180, 60; -60])


是的,它返回
180。–更加模糊的

2

Javascript ES6,87个字节

with(Math)f=(...n)=>(t=>180/PI*atan(t(sin)/t(cos)))(f=>n.reduce((p,c)=>p+=f(c*PI/180)))

运行示例(在Firefox中测试):

f(-91,91)     // -0
f(-90,90)     // 0
f(0,-120,120) // 0
f(0,810)      // 44.999999999999936

工作正在进行中

该版本采用的方法与平均一切然后做模数的方法略有不同。而是将角度转换为向量,将向量相加,然后计算所得向量的角度。不幸的是,这个版本对于Trig 来说非常不稳定,我将研究模块化数学版本。


1
f(-91,91)应该返回
180。– TheNumberOne

1
即使正确实现,矢量加法也无法计算指定的结果。向量加法使角度差的余弦和最大化,而不是使角度差的平方和最小化。
Anders Kaseorg 2015年

2

CJam, 44个  40字节

Ie3_2*,f-:e-2{ea:~f{-P*180/mcmC2#}:+}$0=

CJam解释器中在线尝试。

测试用例

$ for i in 1\ 3 90\ -90 0\ -120\ 120 0\ 810 1\ 3\ 3 180\ 60\ -60 0\ 15\ 45\ 460 91\ -91 -89\ 89
> do cjam <(echo 'Ie3_2*,f-:e-2{ea:~f{-P*180/mcmC2#}:+}$0=') $i
> echo
> done
2.0
180.0
0.0
45.0
2.33
60.0
40.0
180.0
0.0

理念

我们以步长为0.01的步长计算从-179.99180.00的所有潜在平均值的偏差,并选择偏差最小的偏差。

为此,我们取角度距离度数或弧度并不重要。我们可以简单地计算arccos(cos(πδ÷180°)),而不是映射[0,360°)中输入和势均值的角度差δ并有条件地从180°中减去结果,因为cos既是周期的,甚至是偶数,而arccos总是产生[0,π)的值

Ie3        e# Push 18e3 = 18,000.
_2*        e# Copy and multiply by 2. Pushes 36,000.
,          e# Push the range [0 ... 35,999].
f-         e# Subtract each element from 18,000. Pushes [18,000 ... -17,999].
:e-2       e# Divide each element by 100. Pushes [180.00 ... -179.99].
{          e# Sort; for each element A of that array:
  ea:~     e#   Push and evaluate the array of command-line arguments.
  f{       e#   For each input angle, push A and the angle; then:
    -      e#     Subtract the angle from A.
    P*180/ e#     Convert from degrees to radians.
    mcmC   e#     Apply cos, then arccos to the result.
    2#     e#     Square.
  }        e#
  :+       e#   Add the squares. This calculates the deviation.
}$         e# A's with lower deviations come first.
0=         e# Select the first element of the sorted array.

1

MATLAB 151

p=360;n=mod(input(''),p);a=0:0.01:p;m=[];for b=a e=b-n;f=mod([e;-e],p);c=min(f);d=c.^2;m=[m sum(d)];end;[~,i]=min(m);a=a(i);if a>180 a=a-p;end;disp(a);

好的,直到我真正理解方法论是什么,这就是我想出的。这有点骇人听闻,但由于问题指出答案必须正确无误,因此必须正确2.dp。

我基本上检查0到360之间的每个角度(以0.01为增量),然后针对每个角度求解问题中的公式。然后,选择总和最小的角度并将其转换为-180至180范围。


该代码应带有Octave。您可以与在线翻译一起尝试


1°,183°应该是-88°,而不是92°。
Anders Kaseorg 2015年

@AndersKaseorg现在再试一次。
汤姆·卡彭特

不,没关系。再次回到制图板上……
汤姆·卡彭特

1

JavaScript(ES6)138

由于没有最模糊的算法概念,因此尝试以2位数的精度(-179.99至180.00)尝试所有可能的值。无论如何,测试用例都很快速。

测试在符合EcmaScript 6的浏览器中运行以下代码段(实现箭头功能和默认参数-AFAIK Firefox)

A=l=>(D=(a,b,z=a>b?a-b:b-a)=>z>180?360-z:z,m=>{for(i=-18000;i++<18000;)l.some(v=>(t+=(d=D(v%360,i/100))*d)>m,t=0)||(m=t,r=i)})(1/0)||r/100

// Test
console.log=x=>O.innerHTML+=x+'\n'

;[[1,3],[89,-89],[90,-90],[91,-91],[0,120,-120],[0,810],[1,3,3],[180,60,-60],[0,15,45,460],[1,183]]
.forEach(t=>console.log(t+' -> '+A(t)))

// Less golfed

A=l=>{
  D=(a,b,z=a>b?a-b:b-a) => z>180?360-z:z; // angular distance
  m=1/0;
  for(i=-18000;i++<18000;) // try all from -179.99 to 180
  {
    t = 0;
    if (!l.some(v => (t+=(d=D(v%360,i/100))*d) > m))
    {
      m = t;
      r = i;
    }  
  }  
  return r/100;
}
<pre id=O></pre>

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.