角度の平均


15

ストーリー、またはこれを行う理由。

なし。この練習は完全に無意味です...あなたがスティーブンホーキングでない限り。

チャレンジ

角度のリストが与えられたら、それらの角度の平均を見つけます。たとえば、91度と-91度の平均は180度です。これを行うには、プログラムまたは関数を使用できます。

入力

角度測定を表す次数値のリスト。あなたはそれらが整数であると仮定するかもしれません。任意の便利な形式で入力するか、関数の引数として提供できます。

出力

入力された値の平均。平均値に複数の値が見つかった場合は、1つだけを出力する必要があります。平均は、その値として定義されます

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

最小化されます。出力は(-180、180]の範囲内にあり、小数点より少なくとも2桁正確である必要があります。

例:

> 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

場合とに、最小バイトの勝ちます。

リーダーボード

これは、通常のリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットです。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

## Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

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

ヘッダーに複数の数字を含める場合(たとえば、スコアが2つのファイルの合計であるか、インタープリターフラグペナルティーを個別にリストする場合)、実際のスコアがヘッダーの最後の数字であることを確認します。

## 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の平均は180ではなく0です。定義を使用すると、(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°を返すはずです。
アンデルスカセオルグ

回答:


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私は、あなたが変更することにより、1つのバイトを保存することができると思うs**2s*s
Ioannes

質問に対する私のコメントをご覧ください。
msh210

@ msh210なぜこのコメントを私に向けているのかわからない。私のソリューションはすでにそのように機能しています。
アンデルスカセオルグ

これは、この回答投稿の最後の文に対する部分的な返信でした。
msh210

4

Python 3、85バイト

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

可能なすべての角度を増分して試行することにより、小数点以下2桁まで正確である必要があるだけの答えを活用します。 1/200 1度。これは私のマシンでは1秒もかかりません。

Pythonは、私たちは便利な山車の等差数列を一覧表示することはできませんので、我々は全体の数として可能な角度を表して[0,72000)いる変換角度として、(-180,180]などx -> 180 - x/200。角差の二乗の最小和を与えるこれらの1つを見つけます。

角変位がの2つの角度のd場合、角距離の2乗は、(-180,180]as 180-(d+180)%360で同等の角度に変換してから2乗します。便利なことに、で指定された角度x/200はすでに角度でオフセットされてい180ます。


の増分の使用に1/200は実際問題があります。テストケースのために[1, 3, 3]、このソリューションは戻り、正しい答えがあるべきである間、2.335丸められ2.34ます2.33
ジョエル

@Joel丸めの取得元がわかりません2.33。この例では小数桁が正しいようです。いずれにせよ、200to 400またはtoを変更すると2000(それに72000応じて)丸めても機能しますか?また、この古い問題をもう一度見ると、もっと良い方法が見つかるかもしれません。
xnor

0.01m=argmnバツfバツ[ss+0.01]fs<fs+0.01|ms|<|ms+0.01|round(m)=sff(s)>f(s+0.01)f(s)=f(s+0.01)round(m)=s+0.01. Note that for an arbitrary f this property may not be guaranteed.
Joel

Here is a TIO link for you to test.
Joel

Oh, I just realized that you are right. If the correct answer is 2.333... and your program returns 2.335, it is correct until two decimal places without rounding. Sorry for that.
Joel

3

Octave, 97 95 bytes

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

This produces an anonymous function that just searches the minimum of the given function on a grid that is just fine enough. As input the function accepts column vectors, e.g. [180; 60; -60]. For testing you need to give the function a name. So you could e.g. run the code above and then use ans([180, 60; -60]).


Yes, it returns 180.
flawr

2

Javascript ES6, 87 bytes

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

Example runs (Tested in Firefox):

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

Work in progress

This version takes a slightly different approach than the average-everything-then-do-modular-math. Rather, the angles are converted to vectors, the vectors are added and the angle of the resulting vector is then computed. Unfortunately, this version is very unstable with the trig and I'll be working on a modular-math version.


1
f(-91,91) should return 180.
TheNumberOne

1
Even if it were implemented correctly, a vector addition approach cannot compute the specified result. Vector addition maximizes the sum of cosines of angular differences, rather than minimizing the sum of squares of angular differences.
Anders Kaseorg

2

CJam,  44  40 bytes

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

Try it online in the CJam interpreter.

Test cases

$ 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

Idea

We compute the deviation for all potential averages from -179.99 to 180.00 with steps of size 0.01, and select the one with the lowest deviation.

この目的のために、角度距離を度またはラジアンのどちらにするかは問題ではありません。入力からの角​​度の差δをマッピングし、[0,360°)の平均ポテンシャルと180°から条件付きで減算する代わりに、cosは周期的かつ偶数であるため、単純にarccos(cos(πδ÷180°))を計算できます。また、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°は、92°ではなく-88°になります。
アンデルスカセオルグ

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

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