ค่าเฉลี่ยของมุม


15

เรื่องราวหรือสาเหตุที่เรากำลังทำเช่นนี้

ไม่มี. การออกกำลังกายนี้จะไม่มีจุดหมายสมบูรณ์ ... จนกว่าคุณจะได้สตีเฟ่นฮอว์คิง

ความท้าทาย

ให้รายการของมุมหาค่าเฉลี่ยของมุมเหล่านั้น ตัวอย่างเช่นค่าเฉลี่ย 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


ไม่ควร 90, -90 ให้ 180 ถ้า 91, -91 ให้ 180?
Blue

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 ไม่เป็นไรเข้าใจผิด อาจจะ? ตอนนี้ฉันไม่แน่ใจ
Blue

โอเคขอบคุณ. ยังไม่มีความคิดเกี่ยวกับวิธีค้นหามัน
edc65

3
กรณีทดสอบของคุณไม่มีกรณีใดเลยที่จะทำลายอัลกอริธึมที่ไม่ถูกต้องเพียงแค่ปรับมุมทั้งหมด 360 องศาโดยเฉลี่ยแล้วลบ 360 °ถ้าผลลัพธ์มากกว่า 180 ° คุณควรเพิ่มเคสเช่น [89 °, −89 °] ซึ่งควรกลับ 0 °
Anders Kaseorg

คำตอบ:


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**2เป็นs*s
Ioannes

ดูความคิดเห็นของฉันในคำถาม
msh210

@ msh210 ไม่แน่ใจว่าทำไมคุณนำความคิดเห็นนี้มาให้ฉันโดยเฉพาะ โซลูชันของฉันใช้งานได้แล้ว
Anders Kaseorg

มันเป็นบางส่วนในการตอบกลับถึงประโยคสุดท้ายของคำตอบนี้
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

ใช้ประโยชน์จากคำตอบที่ต้องการเพียงความแม่นยำถึงทศนิยมสองตำแหน่งโดยพยายามทำมุมที่เป็นไปได้ทั้งหมดโดยเพิ่มขึ้นทีละ1/200หนึ่งองศา ใช้เวลาน้อยกว่าหนึ่งวินาทีในเครื่องของฉัน

เพราะงูใหญ่ไม่ได้ให้เราในทำเลที่สะดวกรายการก้าวหน้าเลขคณิตของลอยเราเป็นตัวแทนของมุมที่เป็นไปได้เป็นจำนวนทั้งหมด[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จะถูกต้องในตัวอย่างนั้น ไม่ว่าในกรณีใดการเปลี่ยน200ไปเป็น400หรือไป2000(และ72000เหมือนกัน) ทำให้มันทำงานได้แม้จะปัดเศษ? เมื่อดูปัญหาเก่านี้อีกครั้งฉันคิดว่าฉันอาจเห็นวิธีที่ดีกว่า
xnor

0.01ม.=aRก.ม.ผมnx(x)[s,s+0.01](s)<(s+0.01)|ม.-s|<|ม.-s+0.01|Rโอยูnd(ม.)=s(s)>(s+0.01)(s)=(s+0.01)Rโอยูnd(ม.)=s+0.01

นี่คือลิงค์ TIOสำหรับคุณในการทดสอบ
โจเอล

โอ้ฉันเพิ่งรู้ว่าคุณพูดถูก หากคำตอบที่ถูกต้องคือ2.333...และโปรแกรมของคุณส่งคืนคำตอบ2.335นั้นจะถูกต้องจนกว่าจะมีทศนิยมสองตำแหน่งโดยไม่ปัดเศษ ขอโทษสำหรับสิ่งนั้น.
Joel

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

สิ่งนี้สร้างฟังก์ชั่นที่ไม่ระบุชื่อที่เพิ่งค้นหาฟังก์ชันขั้นต่ำที่กำหนดในกริดที่ดีพอ ฟังก์ชั่นเป็น input [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

กำลังดำเนินการ

รุ่นนี้ใช้วิธีการที่แตกต่างกันเล็กน้อยกว่าค่าเฉลี่ย - ทุกอย่าง - แล้ว - ทำ - โมดุล - คณิตศาสตร์ มุมจะถูกแปลงเป็นเวกเตอร์เพิ่มเวกเตอร์และคำนวณมุมของเวกเตอร์ที่ได้ น่าเสียดายที่เวอร์ชันนี้ไม่เสถียรมากกับตรีโกณมิติและฉันจะทำงานกับรุ่นคณิตศาสตร์ - โมดูลาร์


1
f(-91,91)ควรกลับมา 180
TheNumberOne

1
แม้ว่ามันจะถูกนำไปใช้อย่างถูกต้องวิธีการเพิ่มเวกเตอร์ไม่สามารถคำนวณผลลัพธ์ที่ระบุได้ การบวกเวกเตอร์ช่วยเพิ่มผลรวมของความแตกต่างเชิงมุมให้มากที่สุด, แทนที่จะลดผลรวมของกำลังสองของความแตกต่างเชิงมุม
Anders Kaseorg

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

ความคิด

เราคำนวณค่าเบี่ยงเบนสำหรับค่าเฉลี่ยที่อาจเกิดขึ้นทั้งหมดจาก-179.99ถึง180.00ด้วยขนาดขั้นตอน 0.01และเลือกค่าเบี่ยงเบนต่ำสุด

สำหรับจุดประสงค์นี้มันไม่สำคัญว่าเราจะใช้ระยะทางเชิงมุมหรือเรเดียน แทนที่จะทำแผนที่ความแตกต่างδของมุมจากอินพุทและค่าเฉลี่ยที่เป็นไปได้ใน[0,360 °)และการลบผลลัพธ์อย่างมีเงื่อนไขจาก180 °เราสามารถคำนวณarccos (cos (πδ÷ 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


รหัสควรจะมีคู่ คุณสามารถลองกับล่ามออนไลน์


1 °, 183 °ควรส่งผลให้ −88 °ไม่ใช่ 92 °
Anders Kaseorg

@AndersKaseorg ลองอีกครั้งตอนนี้
Tom Carpenter

ไม่ไม่เป็นไร กลับไปที่กระดานวาดภาพอีกครั้ง ...
Tom Carpenter

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.