ศูนย์กลางของสามเหลี่ยม


13

วงกลมและสี่เหลี่ยมมีจุดกึ่งกลางที่ชัดเจน อย่างไรก็ตามแนวคิดของจุดศูนย์กลางของสามเหลี่ยมนั้นได้ถูกกล่าวถึงมานานแล้ว ชาวกรีกโบราณรู้จักศูนย์สี่แห่งที่ต่างกัน:

  • Incenter : จุดตัดของเส้นแบ่งครึ่งมุมของสามเหลี่ยม
  • Centroid : จุดตัดของเส้นจากแต่ละจุดยอดของรูปสามเหลี่ยมไปจนถึงจุดกึ่งกลางของด้านตรงข้าม
  • Circumcenter : จุดตัดของเส้นแบ่งครึ่งตั้งฉากของด้านข้าง
  • Orthocenter : จุดตัดของระดับความสูงของรูปสามเหลี่ยม

ออยเลอร์พิสูจน์ในภายหลังว่า centroid, circumcenter และ orthocenter เป็น collinear ในรูปสามเหลี่ยมใด ๆ บรรทัดที่ทั้งสามจุดอยู่ในรูปสามเหลี่ยมเรียกว่าสายออยเลอร์ มันถูกกำหนดไว้สำหรับทุกสามเหลี่ยมยกเว้นสามเหลี่ยมด้านเท่าซึ่งจุดทั้งหมดตรง

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

1 - Incenter
2 - Centroid
3 - Circumcenter
4 - Orthocenter
5 - Equation of Euler Line
    (if the Euler Line is vertical, output the `x` value of the line
      (e.g. output `5` if the equation of the line is `x = 5`))

คุณอาจสันนิษฐานได้ว่าจุดยอดที่กำหนดจะไม่ collinear และว่าพวกเขาจะเป็นพิกัดจำนวนเต็มเสมอ (สิ่งนี้ยังไม่รวมถึงความเป็นไปได้ของการมีรูปสามเหลี่ยมด้านเท่าเป็นอินพุตตามความคิดเห็นของ @ R.Kap )

อาร์เรย์อินพุตควรเป็นอาร์เรย์ซ้อนกันที่ถูกต้องในภาษาของคุณและอินพุตควรอยู่ในรูปแบบที่เหมาะสม ค่าทศนิยมใด ๆ ควรแสดงเป็นทศนิยมอย่างน้อย 3 ตำแหน่ง แต่ไม่น้อย จุดเอาท์พุทควรเป็นอาร์เรย์ที่ถูกต้องในภาษาของคุณจับคู่กับรูปแบบการป้อนข้อมูล


กรณีทดสอบ:

Input: [(-2, 0), (1, 0), (0, 1)] 1
Output: (-0.089, 0.451)

Input: [(-2, 0), (1, 0), (0, 1)] 2
Output: (-0.333, 0.333)

Input: [(-2, 0), (1, 0), (0, 1)] 3
Output: (-0.5, -0.5)

Input: [(-2, 0), (1, 0), (0, 1)] 4
Output: (0, 2)

Input: [(-2, 0), (1, 0), (0, 1)] 5
Output: 5x + 2

Clarification:อินพุตอาจมาจาก stdin, ช่องว่างหรือบรรทัดใหม่คั่นหรือเป็นอาร์กิวเมนต์ของฟังก์ชัน อย่างไรก็ตามเอาต์พุตต้องถูกเขียนลงใน stdout


1
ฉันเกรงว่าสูตรชัดเจนสำหรับ circumcenter และ orthocenter ในพิกัดคาร์ทีเซียนค่อนข้างน่าเกลียด ถ้าฉันไปทางของการสร้างพิกัด trilinear / barycentric => carthesian ทั่วไป, incenter จะลดลงเกือบฟรี ดูen.wikipedia.org/wiki/Trilinear_coordinates#ตัวอย่าง ฉันจะได้รับคะแนนพิเศษสำหรับการติดตั้งหรือไม่
John Dvorak

รูปแบบเอาต์พุตที่ถูกต้องสำหรับบรรทัดออยเลอร์คืออะไร y=f(x)ถ้ามันเป็นแนวตั้งก็ไม่สามารถจะแสดงเป็น
John Dvorak

1
(โปรดแสดงความคิดเห็นหากคุณไม่เห็นด้วย)โปรดใช้แซนด์บ็อกซ์ถ้าคุณไม่แน่ใจว่าการท้าทายนั้นโอเคหรือไม่ คุณสามารถขอความคิดเห็นและปรับแต่งคำถามได้จนกว่าจะเหมาะสม โพสต์ที่นี่เมื่อมันไม่ควรเปลี่ยนแปลงเกี่ยวกับเนื้อหา หลายคนอาจใช้งานได้แล้ว - และไม่ชอบเป้าหมายที่กำลังเคลื่อนที่
Howard

1
"เมื่อส่งจุดพิกัดจะต้อง ... ล้อมรอบด้วยเครื่องหมายวงเล็บกลม (())" ทำไมความต้องการนี้ ในบางภาษาคะแนนจะถูกแสดงในวงเล็บปีกกา และบางอย่างเช่น (12, -2) สามารถแสดงเป็นสตริงได้เท่านั้นซึ่งในกรณีนี้องค์ประกอบต่างๆจะถูกตีความว่าเป็นสตริงแทนที่จะเป็นตัวเลข
DavidC

1
คุณอาจต้องการทำให้มันเป็นข้อมูลที่สามารถพิกัดจุดลอยตัวหรือกำจัดอย่างสมบูรณ์(if the triangle is equilateral, output the point at which the centers meet)เพราะมันเป็นไปไม่ได้ที่จะสร้างรูปสามเหลี่ยมด้านเท่าบนเครื่องบินพิกัดโดยใช้พิกัดจำนวนเต็มเท่านั้น
R. Kap

คำตอบ:


2

Python - 908 870

เพิ่มบรรทัดใหม่เพื่อลดการเลื่อน นี่อาจจะเป็นกอล์ฟเพิ่มเติม

from math import*;t=eval(input());p=int(input())-1;
r=[];A,B,C=t[0],t[1],t[2];
a,b,c=hypot(B[0]-C[0],B[1]-C[1]),hypot(A[0]-C[0],A[1]-C[1]),hypot(A[0]-B[0],A[1]-B[1]);
r.append(((a*A[0]+b*B[0]+c*C[0])/(a+b+c),(a*A[1]+b*B[1]+c*C[1])/(a+b+c)));
r.append(((A[0]+B[0]+C[0])/3,(A[1]+B[1]+C[1])/3));d,e,f=(0,0),(B[0]-A[0],B[1]-A[1]),(C[0]-A[0],C[1]-A[1]);g=2*(e[0]*f[1]-e[1]*f[0]);
r.append(((f[1]*(e[0]**2+e[1]**2)-e[1]*(f[0]**2+f[1]**2))/g+A[0],(e[0]*(f[0]**2+f[1]**2)- f[0]*(e[0]**2+e[1]**2))/g+A[1]));
h=acos((b*b+c*c-a*a)/(2*b*c));i=acos((a*a+c*c-b*b)/(2*a*c));j=acos((a*a+b*b- c*c)/(2*a*b));k=cos(i)*cos(j);
l=cos(h)*cos(j);m=cos(h)*cos(i);r.append(((a*k*A[0]+b*l*B[0]+c*m*C[0])/(a*k+b*l+c*m),(a*k*A[1]+b*l*B[1]+c*m*C[1])/(a*k+b*l+c*m)));
n,o=r[1][0]-r[2][0],r[1][1]-r[2][1];q=r[1][1]-o/n*r[1][0]if n!=0 else 0;
r.append(r[1]if a==b==c else("x="+str(r[1][0])if n==0 else"".join([str(o/n),"x+(",str(q),")"])));print(r[p])

กรณีทดสอบ (หมายเหตุประกอบ):

Input: [(-2, 0), (1, 0), (0, 1)]
1
Output: (-0.08907279243665268, 0.45110872103880023) --> More digits than in question

Input: [(-2, 0), (1, 0), (0, 1)]
2
Output: (-0.3333333333333333, 0.3333333333333333) --> More digits than in question

Input: [(-2, 0), (1, 0), (0, 1)]
3
Output: (-0.5, -0.5)

Input: [(-2, 0), (1, 0), (0, 1)]
4
Output: (-1.1702778228588997e-16, 1.9999999999999984) --> More digits than shown in question

Input: [(-2, 0), (1, 0), (0, 1)]
5
Output: 4.999999999999999x+(1.9999999999999996) --> More digits than in question

อย่างที่คุณเห็นอาจมีข้อผิดพลาดเกิดขึ้นจากการใช้จุดลอย


กอล์ฟเพิ่มเติม:

จากคำแนะนำในความคิดเห็นด้านล่างฉันได้พยายามทำให้เรื่องเล็กลง

from math import*;I=input;t=eval(I());p=int(I())-1;r=[];A,B,C=t[0],t[1],t[2];R,H,D,S,T=r.append,hypot,cos,acos,str;a,b,c=H(B[0]-C[0],B[1]-C[1]),H(A[0]-C[0],A[1]-C[1]),H(A[0]-B[0],A[1]-B[1]);R(((a*A[0]+b*B[0]+c*C[0])/(a+b+c),(a*A[1]+b*B[1]+c*C[1])/(a+b+c)));R(((A[0]+B[0]+C[0])/3,(A[1]+B[1]+C[1])/3));d,e,f=(0,0),(B[0]-A[0],B[1]-A[1]),(C[0]-A[0],C[1]-A[1]);g=2*(e[0]*f[1]-e[1]*f[0]);R(((f[1]*(e[0]**2+e[1]**2)-e[1]*(f[0]**2+f[1]**2))/g+A[0],(e[0]*(f[0]**2+f[1]**2)-f[0]*(e[0]**2+e[1]**2))/g+A[1]));h=S((b*b+c*c-a*a)/(2*b*c));i=S((a*a+c*c-b*b)/(2*a*c));j=S((a*a+b*b-c*c)/(2*a*b));k=D(i)*D(j);l=D(h)*D(j);m=D(h)*D(i);R(((a*k*A[0]+b*l*B[0]+c*m*C[0])/(a*k+b*l+c*m),(a*k*A[1]+b*l*B[1]+c*m*C[1])/(a*k+b*l+c*m)));n,o=r[1][0]-r[2][0],r[1][1]-r[2][1];q=r[1][1]-o/n*r[1][0]if n!=0else 0;R(r[1]if a==b==c else("x="+T(r[1][0])if n==0else"".join([T(o/n),"x+(",T(q),")"])));print(r[p])


1
คุณสามารถทำสิ่งที่ชอบR=r.appendแล้วใช้มันตลอดเพื่อบันทึกไบต์?
FlipTack

1

AutoHotkey - 731

f(z, r:=1){
static 1:="i",2:="m",3:="c",4:="o"
r := %r%,mx :=(z.1.1+z.2.1+z.3.1)/3,my:=(z.1.2+z.2.2+z.3.2)/3
s:=(c:=sqrt((z.2.1-z.1.1)**2+(z.2.2-z.1.2)**2))+(a:=sqrt((z.3.1-z.2.1)**2+(z.3.2-z.2.2)**2))+(b:=sqrt((z.3.1-z.1.1)**2+(z.3.2-z.1.2)**2))
ix:=(a*z.1.1+b*z.2.1+c*z.3.1)/s,iy:=(a*z.1.2+b*z.2.2+c*z.3.2)/s
midx_a:=(z.3.1+z.2.1)/2,midy_a:=(z.3.2+z.2.2)/2,m:=-1*(z.3.1-z.2.1)/(z.3.2-z.2.2),cc_a:=midy_a-(m*midx_a)
midx_b:=(z.3.1+z.1.1)/2,midy_b:=(z.3.2+z.1.2)/2,n:=-1*(z.3.1-z.1.1)/(z.3.2-z.1.2),cc_b:=midy_b-(n*midx_b)
cx:=(cc_b-cc_a)/(m-n),cy:=cc_a+(m*cx),oc_a:=z.1.2-(m*z.1.1),oc_b:=z.2.2-(n*z.2.1),ox:=(oc_a-oc_b)/(n-m),oy:=oc_a+(m*ox)
if r in m,i,c,o
return [%r%x, %r%y]
else return "y=" (m:=(oy-cy)/(ox-cx)) "x+" oy-m*ox
}

ฟังก์ชั่นสามารถลดขนาดได้มากขึ้น (ประมาณ 600 ตัวอักษรหรือน้อยกว่า) โดยการย่อชื่อตัวแปรเช่น midx_a, midx_b และอื่น ๆ

กำลังเรียกใช้ฟังก์ชัน

d:=f([[-2, 0], [1, 0], [0, 1]], 1)
for k,v in d
    msgbox % k "`n" v

1

Python 3.5, 851 772 ไบต์:

def H(z,a,b,l):c=complex;T=lambda A,B:abs(c(*A)-c(*B));d=T(z,a);e=T(z,b);f=T(a,b);g=[((a[0]+b[0])/2,(a[1]+b[1])/2)for a,b in[[a,b],[z,a],[b,z]]];E=(z[0]+a[0]+b[0])/3;F=(z[1]+a[1]+b[1])/3;m=lambda f:[(a,0)if(b[1][0]-b[0][0])==0else(a,-1/((b[1][1]-b[0][1])/(b[1][0]-b[0][0])))if(b[1][1]-b[0][1])else''for a,b in zip(f,[[a,b],[z,a],[b,z]])];i=[u for u in m(g)if u!=''];C=i[0][1];D=i[0][0][1]-(C*i[0][0][0]);A=i[1][1];B=i[1][0][1]-(A*i[1][0][0]);G=(B-D)/(C-A);H=C*G+D;j=[u for u in m([z,b,a])if u!=''];C=j[0][1];D=j[0][0][1]-(C*j[0][0][0]);A=j[1][1];B=j[1][0][1]-(A*j[1][0][0]);I=(B-D)/(C-A);J=C*I+D;K,L=[((d*b[o])+(e*a[o])+(f*z[o]))/sum([d,e,f])for o in[0,1]];a=(H-J)/(G-I)if(G-I)else'';b=H-(a*G)if a!=''else G;print(['',(K,L),(E,F),(G,H),(I,J),[b,'%sx+%s'%(a,b)][a!='']][l])

ใช้เวลาการป้อนข้อมูลเป็นลำดับของพิกัดคั่นด้วยเครื่องหมายจุลภาคตามด้วยจำนวนเต็มนำพาสิ่งที่จะส่งออก ตัวอย่างเช่นถ้าพิกัดอินพุต(1,0),(2,1),(1,4)และคุณต้องการให้ orthocenter ของสามเหลี่ยมสอดคล้องกับพิกัดเหล่านั้นคุณก็จะเรียกฟังก์ชันดังกล่าวดังนี้

H((1,0),(2,1),(1,4),4)

เอาต์พุตในรูปแบบของ tuple หากต้องการจุดเฉพาะในรูปแบบของสตริงที่มีสมการในรูปแบบy=mx+bหากต้องการใช้สาย Euler และเส้นไม่ได้เป็นแนวตั้งหรือเพียงแค่xค่าของบรรทัดถ้าสาย Euler จำเป็นต้องมี แต่บรรทัดนั้นเป็นแนวตั้ง

ดังนั้นการใช้สามเหลี่ยมกับจุดยอด(1,0),(2,1),(1,4)ผลลัพธ์จะเป็น:

1. Incenter: (1.4663911961440428, 1.125967951102358)
2. Centroid: (1.3333333333333333, 1.6666666666666667)
3. Circumcenter: (0.0, 2.0)
4. Orthocenter: (4.0, 1.0)
5. Euler Line: -0.25x+2.0 

ฉันจะพยายามเล่นกอล์ฟให้มากขึ้นเมื่อเวลาผ่านไป

ลองออนไลน์! (Ideone)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.