Açıların Ortalamaları


15

Hikaye veya bunu neden yapıyoruz.

Yok. Bu egzersiz tamamen anlamsız ... Stephen Hawking değilseniz .

Meydan okuma

Bir açı listesi verildiğinde, bu açıların ortalamasını bulun. Örneğin, 91 derece ve -91 derecenin ortalaması 180 derecedir. Bunu yapmak için bir program veya işlev kullanabilirsiniz.

Giriş

Açı ölçülerini temsil eden derece değerlerinin listesi. Bunların tamsayı olacağını varsayabilirsiniz. Herhangi bir uygun biçimde girilebilir veya işlev argümanları olarak sağlanabilirler.

Çıktı

Girilen değerlerin ortalaması. Ortalama için birden fazla değer bulunursa, yalnızca bir değer çıkarılmalıdır. Ortalama,

resim açıklamasını buraya girin

simge durumuna küçültülür. Çıktı (-180, 180] aralığında olmalı ve ondalık noktasının arkasındaki en az iki yere kadar doğru olmalıdır.

Örnekler:

> 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

ile her zamanki gibi , en az bayt ile gönderme kazanır.

Liderler Sıralaması

İşte hem düzenli bir skor tablosu hem de kazananları dile göre gözden geçirmek için bir Yığın Parçacığı.

Yanıtınızın göründüğünden emin olmak için lütfen aşağıdaki Markdown şablonunu kullanarak yanıtınızı bir başlıkla başlatın:

## Language Name, N bytes

Ngönderiminizin büyüklüğü nerede . Puanınızı artırmak varsa, olabilir onları içinden vurarak, başlığa eski hesapları tutmak. Örneğin:

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

Başlığınıza birden fazla sayı eklemek istiyorsanız (örneğin, puanınız iki dosyanın toplamı olduğu veya yorumlayıcı bayrak cezalarını ayrı olarak listelemek istediğiniz için), gerçek puanın başlıktaki son sayı olduğundan emin olun :

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

Dil adını, daha sonra skor tablosu snippet'inde görünecek bir bağlantı da yapabilirsiniz:

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

Sorunla ilgili sorularınız için bir sohbet odası: http://chat.stackexchange.com/rooms/30175/room-for-average-of-angles


91, -91 180 veriyorsa 90, -90 180 vermez mi?
Mavi

2
Sezgisel olarak -91 ve 91 ortalaması 180 değil, 0'dır. Tanımınızı kullanarak: (180-91) ^ 2 + (180- -91) ^ 2 => 81362, (0-91) ^ 2 + ( 0- -91) ^ 2 => 16562. Yani 180 kesinlikle ortalama olamaz. Burada ne eksik?
edc65

91% = 91 360; -91% 360 = 269 (269 + 91) / 2 = 180. Boş ver, yanlış oku. Olabilir? Şimdi emin değilim.
Mavi

Tamam teşekkürler. Nasıl bulmak hakkında hala bir fikir yok
edc65

3
Test durumlarınızdan hiçbiri, tüm açıları 360 ° almak, ortalamalarını almak ve sonuç 180 ° 'den büyükse 360 ​​° çıkarmak için yanlış algoritmayı kırmaz. [89 °, −89 °] gibi 0 ° döndürmesi gereken bir durum eklemelisiniz.
Anders Kaseorg

Yanıtlar:


7

Python 3, 129 bayt

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]

Bu sorun oldukça fazla karışıklığa neden olmuş gibi görünüyor. Sezgisel olarak, fikir, açı çemberini bir noktada kesmek, daireyi bir çizgiye açmak, o satırdaki aritmetik ortalamayı hesaplamak ve ardından sonucu tekrar daireye sarmaktır. Ancak daireyi kesmeyi seçebileceğiniz birçok farklı nokta var. 0 ° veya 180 ° gibi keyfi olarak bir tane seçmek yeterli değildir. Hepsini denemeniz ve hangisinin kare mesafelerin en küçük toplamıyla sonuçlandığını görmeniz gerekir. Çözümünüz bundan daha az karmaşıksa, muhtemelen yanlıştır.


1
@AndreasKaseorg Sana değiştirerek bir bayt kurtarabilir miyiz s**2içins*s
Ioannes

Soru hakkındaki yorumuma bakın.
msh210

@ msh210 Bu yorumu neden özellikle bana yönlendirdiğinizden emin değilim. Çözümüm zaten bu şekilde çalışıyor.
Anders Kaseorg

Kısmen bu cevap mesajının son cümlesine cevaptı.
msh210

4

Python 3, 85 bayt

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

1/200Bir derecenin artışları ile tüm olası açıları deneyerek sadece iki ondalık basamağa doğru olması gereken cevaptan yararlanır . Bu makinemde bir saniyeden az sürüyor.

Python, şamandıraların aritmetik ilerlemelerini rahatça listelememize izin vermediğinden [0,72000), bir açıyı olduğu (-180,180]gibi dönüştüren olası açıları tam sayı olarak temsil ederiz x -> 180 - x/200. Bunlardan en az kare açısal farklılıkların toplamını veren birini buluyoruz.

Bir açısal yer değiştirme ile, iki açıları için d, kare açısal mesafe eşdeğer bir açıya dönüştürerek bulunmuştur (-180,180]olarak 180-(d+180)%360daha sonra, kare alma. Uygun olarak, verilen açı derece ile x/200dengelenmiştir 180.


Artışlarını kullanmak 1/200aslında sorunlu. Test senaryosu için [1, 3, 3], bu çözüm geri döner 2.335ve 2.34doğru cevap alınırken yuvarlanır 2.33.
Joel

@Joel Yuvarlamayı nereden aldığınızdan emin değilim, ondalık basamaklar 2.33bu örnekteki gibi görünüyor . Her durumda, değişen olacağını 200etmek 400veya 2000(ve 72000buna) yuvarlama rağmen o iş yapmak? Ayrıca, bu eski soruna tekrar bakarak daha iyi bir yol görebileceğimi düşünüyorum.
xnor

0.01m=birrgmbennxf(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)round(m)=s+0.01f

İşte test etmeniz için bir TIO bağlantısı .
Joel

Oh, sadece haklı olduğunu fark ettim. Doğru cevap 2.333...ve programınız geri dönüyorsa 2.335, yuvarlamadan iki ondalık basamağa kadar doğrudur. Bunun için özür dilerim.
Joel

3

Oktav, 97 95 bayt

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

Bu, bir ızgarada verilen işlevin minimumunu sadece yeterince iyi olan anonim bir işlev üretir. Giriş olarak fonksiyon sütun vektörlerini kabul eder, örn [180; 60; -60]. Test için işleve bir ad vermeniz gerekir. Böylece yukarıdaki kodu çalıştırabilir ve kullanabilirsiniz ans([180, 60; -60]).


Evet, 180 döndürür.
flawr

2

Javascript ES6, 87 bayt

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

Örnek çalıştırmalar (Firefox'ta test edildi):

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

Devam eden çalışma

Bu sürüm ortalama-her şey-sonra-modüler-matematik biraz daha farklı bir yaklaşım alır. Aksine, açılar vektörlere dönüştürülür, vektörler eklenir ve elde edilen vektörün açısı daha sonra hesaplanır. Ne yazık ki, bu sürüm trig ile çok kararsız ve modüler matematik sürümü üzerinde çalışacağım.


1
f(-91,91)180 dönmelidir.
TheNumberOne

1
Doğru bir şekilde uygulansa bile, bir vektör ekleme yaklaşımı belirtilen sonucu hesaplayamaz. Vektör ilavesi, açısal farklılıkların karelerinin toplamını minimize etmek yerine, açısal farklılıkların kosinüslerinin toplamını maksimuma çıkarır.
Anders Kaseorg

2

CJam,  44  40 bayt

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

CJam yorumlayıcısında çevrimiçi deneyin .

Test senaryoları

$ 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

Fikir

0.01 büyüklüğündeki adımlarla -179.99 ila 180.00 arasındaki tüm potansiyel ortalamalar için sapmayı hesaplıyoruz ve en düşük sapmaya sahip olanı seçiyoruz.

Bu amaçla, açısal mesafeleri derece veya radyan almamızın önemi yoktur. [0,360 °) cinsinden giriş ve potansiyel ortalamalardan açıların δ farklarını haritalamak ve sonucu 180 ° ' den şartlı olarak çıkarmak yerine , arkosları (cos (πδ ÷ 180 °)) hesaplayabiliriz , çünkü cos hem periyodik hem de çift, ve arccos her zaman [0, π) cinsinden bir değer verir .

kod

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);

Tamam, bu yüzden metodolojinin ne olduğunu gerçekten anlayana kadar, bu benim ortaya çıkardığım şeydi. Bu biraz hack, ama soru belirttiği gibi cevap 2.dp için doğru olması gerekir.

Temelde 0 ile 360 ​​arasındaki her bir açıyı kontrol ediyorum (0,01'lik artışlarla) ve sonra bu açıların her biri için sorudaki formülü çözdüm. Daha sonra, en küçük toplamı olan açı seçilir ve -180 ila 180 aralığına dönüştürülür.


Kod Octave ile olmalıdır . Çevrimiçi yorumlayıcı ile deneyebilirsiniz


1 °, 183 °, 92 ° değil −88 ° ile sonuçlanmalıdır.
Anders Kaseorg

@AndersKaseorg şimdi tekrar deneyin.
Tom Carpenter

Hayır, boş ver. Tekrar çizim tahtasına geri dönün
Tom Carpenter

1

JavaScript (ES6) 138

En ince bir algoritma fikrine sahip olmayan, bu mümkün olan tüm değerleri 2 basamak hassasiyetle (-179,99 ila 180,00) dener. Zaten test senaryoları ile oldukça hızlı.

Aşağıdaki snippet'i EcmaScript 6 uyumlu bir tarayıcıda çalıştırmayı test edin (ok işlevlerini ve varsayılan parametreleri uygulama - 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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.