Mittelwerte der Winkel

15

Geschichte, oder warum wir das tun.

Keiner. Diese Übung ist völlig sinnlos ... es sei denn, Sie sind Stephen Hawking .

Die Herausforderung

Ermitteln Sie anhand einer Liste von Winkeln den Durchschnitt dieser Winkel. Zum Beispiel ist der Durchschnitt von 91 Grad und -91 Grad 180 Grad. Sie können dazu ein Programm oder eine Funktion verwenden.

Eingang

Eine Liste von Gradwerten, die Winkelmaße darstellen. Sie können davon ausgehen, dass es sich um ganze Zahlen handelt. Sie können in einem beliebigen Format eingegeben oder als Funktionsargumente angegeben werden.

Ausgabe

Der Durchschnitt der eingegebenen Werte. Wenn mehr als ein Wert für den Durchschnitt gefunden wird, sollte nur einer ausgegeben werden. Der Durchschnitt ist definiert als der Wert, für den

Bildbeschreibung hier eingeben

minimiert wird. Die Ausgabe muss im Bereich von (-180, 180] liegen und auf mindestens zwei Stellen hinter dem Dezimalpunkt genau sein.

Beispiele:

> 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

Wie bei üblich, die Einsendung mit den wenigsten Bytes.

Bestenliste

Hier ist ein Stack-Snippet, um sowohl eine reguläre Rangliste als auch eine Übersicht der Gewinner nach Sprache zu generieren.

Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

## Language Name, N bytes

Wo Nist die Größe Ihres Beitrags? Wenn Sie Ihren Score zu verbessern, Sie können alte Rechnungen in der Überschrift halten, indem man sich durch das Anschlagen. Zum Beispiel:

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

Wenn Sie mehrere Zahlen in Ihre Kopfzeile aufnehmen möchten (z. B. weil Ihre Punktzahl die Summe von zwei Dateien ist oder wenn Sie die Strafen für Interpreter-Flags separat auflisten möchten), stellen Sie sicher, dass die tatsächliche Punktzahl die letzte Zahl in der Kopfzeile ist:

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

Sie können den Namen der Sprache auch als Link festlegen, der dann im Leaderboard-Snippet angezeigt wird:

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

Hier finden Sie einen Chatroom für Fragen zum Problem: http://chat.stackexchange.com/rooms/30175/room-for-average-of-angles

Die Nummer eins
quelle
Sollte 90, -90 nicht 180 ergeben, wenn 91, -91 180 ergeben?
Blue
2
Intuitiv ist der Durchschnitt von -91 und 91 0, nicht 180. Nach Ihrer Definition haben wir: (180-91) ^ 2 + (180- -91) ^ 2 => 81362, während (0-91) ^ 2 + ( 0- -91) ^ 2 => 16562. Also 180 kann sicher nicht der Durchschnitt sein. Was vermisse ich hier?
edc65
91% 360 = 91; -91% 360 = 269; (269 + 91) / 2 = 180. Macht nichts, falsch verstanden. Könnte sein? Ich bin mir jetzt nicht sicher.
Blue
OK danke. Immer noch keine Ahnung, wie es zu finden
edc65
3
Keiner Ihrer bisherigen Testfälle widerspricht dem falschen Algorithmus, einfach alle Winkel mod 360 ° zu nehmen, ihren Durchschnitt zu bilden und dann 360 ° zu subtrahieren, wenn das Ergebnis größer als 180 ° ist. Sie sollten einen Fall wie [89 °, −89 °] hinzufügen, der 0 ° zurückgeben sollte.
Anders Kaseorg

Antworten:

7

Python 3, 129 Bytes

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]

Dieses Problem scheint ziemlich viel Verwirrung gestiftet zu haben. Intuitiv besteht die Idee darin, den Winkelkreis an einem bestimmten Punkt zu schneiden, den Kreis zu einer Linie zu lösen, den arithmetischen Mittelwert auf dieser Linie zu berechnen und das Ergebnis dann wieder in den Kreis zu setzen. Es gibt jedoch viele verschiedene Punkte, an denen Sie den Kreis abschneiden können. Es reicht nicht aus, einen willkürlich auszuwählen, z. B. 0 ° oder 180 °. Sie müssen sie alle ausprobieren und sehen, welches die kleinste Summe der quadratischen Abstände ergibt. Wenn Ihre Lösung wesentlich unkomplizierter ist, ist sie wahrscheinlich falsch.

Anders Kaseorg
quelle
1
@ AndreasKaseorg Ich denke, Sie können ein Byte sparen, indem Sie s**2aufs*s
Ioannes
Siehe meinen Kommentar zu der Frage.
msh210
@ msh210 Ich bin mir nicht sicher, warum Sie diesen Kommentar speziell an mich richten. Meine Lösung funktioniert schon so.
Anders Kaseorg
Es war teilweise eine Antwort auf den letzten Satz dieses Antwortpostens.
msh210
4

Python 3, 85 Bytes

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

Profitiert von der Antwort, die nur auf zwei Dezimalstellen genau sein muss, indem alle möglichen Winkel in Schritten 1/200von einem Grad ausprobiert werden . Dies dauert auf meinem Computer weniger als eine Sekunde.

Da wir in Python die arithmetischen Abläufe von Gleitkommazahlen nicht bequem auflisten können, stellen wir die möglichen Winkel als ganze Zahl dar [0,72000), die in einen Winkel als (-180,180]umgerechnet werden x -> 180 - x/200. Wir finden diejenige, die die minimale Summe der quadratischen Winkeldifferenzen ergibt.

Für zwei Winkel mit einer Winkelverschiebung von dwird der quadratische Winkelabstand durch Transformation in einen äquivalenten Winkel in ermittelt(-180,180] as 180-(d+180)%360und anschließendes Quadrieren ermittelt. Zweckmäßigerweise ist der von angegebene Winkel x/200bereits um 180Grad versetzt.

xnor
quelle
Die Verwendung von Inkrementen von 1/200ist tatsächlich problematisch. Für den Testfall wird [1, 3, 3]diese Lösung zurückgegeben 2.335und auf 2.34die richtige Antwort gerundet 2.33.
Joel
@Joel Ich bin mir nicht sicher, woher Sie die Rundung nehmen. Es sieht so aus, als ob die Dezimalstellen 2.33in diesem Beispiel richtig sind. Würde eine Änderung des 200to 400oder to 2000(und 72000entsprechend) trotz Rundung funktionieren? Wenn ich mir dieses alte Problem noch einmal ansehe, denke ich, dass ich vielleicht einen besseren Weg sehe.
27.
0,01m=einrGmichnxf(x)[s,s+0,01]f(s)<f(s+0,01)|m-s|<|m-s+0,01|rÖund(m)=sff(s)>f(s+0,01)f(s)=f(s+0,01)rÖund(m)=s+0,01f
Hier ist ein TIO-Link, den Sie testen können.
Joel
Oh, ich habe gerade gemerkt, dass du recht hast. Wenn die richtige Antwort lautet 2.333...und Ihr Programm zurückkehrt 2.335, ist sie bis auf zwei Dezimalstellen ohne Rundung korrekt. Das tut mir leid.
Joel
3

Oktave, 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

Dies erzeugt eine anonyme Funktion, die nur das Minimum der angegebenen Funktion in einem Raster durchsucht, das gerade gut genug ist. Als Eingabe akzeptiert die Funktion Spaltenvektoren, z [180; 60; -60]. Zum Testen müssen Sie der Funktion einen Namen geben. So könntest du zB den obigen Code ausführen und dann verwenden ans([180, 60; -60]).

fehlerhaft
quelle
Ja, es gibt 180 zurück.
Fehler
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)))

Beispiel läuft (Getestet in Firefox):

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

In Arbeit

Diese Version hat einen etwas anderen Ansatz als die Durchschnitts-Alles-Dann-Tun-Modul-Mathematik. Vielmehr werden die Winkel in Vektoren umgewandelt, die Vektoren addiert und der Winkel des resultierenden Vektors berechnet. Leider ist diese Version mit dem Trigger sehr instabil und ich werde an einer modularen Mathematikversion arbeiten.

Dendrobium
quelle
1
f(-91,91)sollte 180 zurückgeben.
TheNumberOne
1
Selbst wenn es korrekt implementiert wurde, kann ein Vektoradditionsansatz das angegebene Ergebnis nicht berechnen. Die Vektoraddition maximiert die Summe der Cosinus-Winkelunterschiede, anstatt die Summe der Quadrate der Winkelunterschiede zu minimieren.
Anders Kaseorg
2

CJam,  44  40 Bytes

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

Probieren Sie es online im CJam-Interpreter aus .

Testfälle

$ 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

Idee

Wir berechnen die Abweichung für alle möglichen Durchschnitte von -179,99 bis 180,00 mit Schritten der Größe 0,01 , und wählen Sie den mit der niedrigsten Abweichung.

Für diesen Zweck spielt es keine Rolle, ob wir die Winkelabstände Grad oder Bogenmaß nehmen. Anstatt die Differenzen δ der Winkel von Eingangs- und Potentialmittelwerten in [0,360 °) abzubilden und das Ergebnis von 180 ° bedingt zu subtrahieren , können wir einfach Arccos (cos (πδ ÷ 180 °)) berechnen , da cos sowohl periodisch als auch gerade ist. und arccos ergibt immer einen Wert in [0, π) .

Code

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.
Dennis
quelle
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);

Okay, bis ich wirklich verstehe, was die Methodik ist, habe ich mir das ausgedacht. Es ist ein kleiner Hack, aber da die Frage besagt, dass die Antwort auf 2.dp korrekt sein muss, sollte es funktionieren.

Grundsätzlich überprüfe ich jeden Winkel zwischen 0 und 360 (in Schritten von 0,01) und löse dann die Formel in der Frage für jeden dieser Winkel. Dann wird der Winkel mit der kleinsten Summe ausgewählt und in einen Bereich von -180 bis 180 umgewandelt.


Der Code sollte mit Octave sein . Sie können es mit dem Online-Dolmetscher versuchen

Tom Carpenter
quelle
1 °, 183 ° sollte −88 ° ergeben, nicht 92 °.
Anders Kaseorg
@AndersKaseorg versuchen Sie es jetzt erneut.
Tom Carpenter
Nein, egal. Zurück zum Zeichenbrett ...
Tom Carpenter
1

JavaScript (ES6) 138

Da Sie nicht die geringste Ahnung von einem Algorithmus haben, werden alle möglichen Werte mit einer Genauigkeit von 2 Stellen (-179,99 bis 180,00) geprüft. Ziemlich schnell mit den Testfällen.

Testen Sie das folgende Snippet in einem EcmaScript 6-kompatiblen Browser (Implementierung von Pfeilfunktionen und Standardparametern - 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>

edc65
quelle