Die Zentren eines Dreiecks

13

Kreise und Quadrate haben einen einzigen, bestimmten Mittelpunkt. Der Begriff des Mittelpunkts eines Dreiecks ist jedoch schon lange diskutiert worden. Den alten Griechen waren vier verschiedene Zentren bekannt:

  • Incenter : Der Schnittpunkt der Winkelhalbierenden des Dreiecks
  • Schwerpunkt : Der Schnittpunkt der Linien von jedem Scheitelpunkt des Dreiecks zur Mitte der gegenüberliegenden Seite
  • Circumcenter : Der Schnittpunkt der senkrechten Winkelhalbierenden der Seiten
  • Orthozentrum : Der Schnittpunkt der Höhen des Dreiecks

Euler bewies später, dass der Schwerpunkt, das Zirkumzentrum und das Orthozentrum in jedem Dreieck kollinear sind. Die Linie, auf der sich diese drei Punkte in einem Dreieck befinden, wird als Euler-Linie bezeichnet . Es wird für jedes Dreieck definiert, mit Ausnahme eines gleichseitigen Dreiecks, bei dem alle Punkte zusammenfallen.

Ihre Herausforderung besteht darin, das kürzeste Programm oder die kürzeste Funktion zu erstellen, die bei zwei Eingaben einen bestimmten Mittelpunkt oder die Euler-Linie des Dreiecks ausgibt. Die erste gibt die Koordinaten jedes Scheitelpunkts eines Dreiecks an. Die Sekunde ist eine Ganzzahl von 1 bis 5, die bestimmt, was ausgegeben werden soll.

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

Sie können davon ausgehen, dass die angegebenen Eckpunkte niemals kollinear und immer ganzzahlige Koordinaten sind (dies schließt auch die Möglichkeit aus, ein gleichseitiges Dreieck als Eingabe gemäß dem Kommentar von @ R.Kap zu verwenden ).

Das Eingabearray sollte ein gültiges verschachteltes Array in Ihrer Sprache sein und die Eingabe sollte in einem angemessenen Format erfolgen. Alle Float-Werte sollten mit mindestens 3 Dezimalstellen, jedoch nicht weniger, angezeigt werden. Ein ausgegebener Punkt sollte ein gültiges Array in Ihrer Sprache sein, das mit dem Eingabeformat übereinstimmt.


Testfälle:

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

Erläuterung: Die Eingabe kann entweder von stdin, durch Leerzeichen oder Zeilenumbrüche getrennt oder als Argument für eine Funktion erfolgen. Die Ausgabe muss jedoch auf stdout geschrieben werden.

Flüchtigkeit
quelle
1
Ich fürchte, explizite Formeln für das Zirkumzentrum und das Orthozentrum in kartesischen Koordinaten sind ziemlich hässlich. Wenn ich den Weg gehe, allgemeine trilineare / baryzentrische => karthesische Koordinaten zu erstellen, fällt der Incenter fast frei aus. Siehe en.wikipedia.org/wiki/Trilinear_coordinates#Examples . Erhalte ich zusätzliche Punkte für die Implementierung?
John Dvorak
Was sind die gültigen Ausgabeformate für die Euler-Linie? Wenn es vertikal ist, kann es nicht als ausgedrückt werden y=f(x).
John Dvorak
1
(Bitte kommentieren Sie, wenn Sie anderer Meinung sind.) Verwenden Sie die Sandbox, wenn Sie sich nicht sicher sind, ob eine Herausforderung in Ordnung ist oder nicht. Dort können Sie nach Kommentaren fragen und die Frage verfeinern, bis sie passt. Einmal hier gepostet, sollte es inhaltlich nicht mehr verändert werden. Möglicherweise arbeiten bereits mehrere Personen daran - und sie mögen es nicht, Ziele zu bewegen.
Howard
1
Msgstr "Bei der Ausgabe eines Punktes müssen die Koordinaten ... in runden Klammern (()) stehen". Warum diese Anforderung? In einigen Sprachen werden Punkte in geschweiften Klammern dargestellt. Und so etwas wie (12, -2) kann nur als Zeichenfolge dargestellt werden. In diesem Fall werden die Elemente selbst als Zeichenfolgen und nicht als Zahlen interpretiert.
DavidC
1
Sie können entweder festlegen, dass die Eingabe Gleitkommakoordinaten sein kann, oder sie können vollständig entfernt werden, (if the triangle is equilateral, output the point at which the centers meet)da es nicht möglich ist, ein gleichseitiges Dreieck in der Koordinatenebene nur mit ganzzahligen Koordinaten zu erstellen.
R. Kap

Antworten:

2

Python - 908 870

Zeilenumbrüche wurden hinzugefügt, um das Scrollen zu reduzieren. Dies könnte wahrscheinlich weiter golfen werden.

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

Testfälle (kommentiert):

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

Wie Sie sehen können, sind möglicherweise Fehler durch die Verwendung von Gleitkommazahlen zu erwarten.


Weiteres Golfen:

Aufgrund der Vorschläge in den Kommentaren unten habe ich es geschafft, dies zu verkleinern.

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])
golfer9338
quelle
Ich denke, es ist eigentlich 907 Bytes. (URL gekürzt).
Erik der Outgolfer
1
Könnten Sie so etwas tun R=r.appendund dann das durchgehend verwenden, um Bytes zu sparen?
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
}

Die Funktion kann durch Kürzen der Variablennamen wie midx_a, midx_b usw. weiter verkleinert werden (auf etwa 600 Zeichen ODER weniger).

Funktion aufrufen

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

Python 3.5, 851 772 Bytes:

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

Nimmt die Eingabe als Folge von durch Kommas getrennten Koordinaten, gefolgt von einer Ganzzahl, die angibt, was ausgegeben werden soll. Wenn zum Beispiel die Eingabekoordinaten lauten (1,0),(2,1),(1,4)und Sie möchten, dass das Orthozentrum des Dreiecks diesen Koordinaten entspricht, würden Sie die Funktion einfach wie folgt aufrufen:

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

Gibt das Format eines Tupels aus, wenn ein bestimmter Punkt benötigt wird, das Format einer Zeichenfolge mit der Gleichung in der Form, y=mx+bwenn die Euler-Linie benötigt wird und die Linie nicht vertikal ist, oder einfach den xWert der Linie, wenn die Euler-Linie benötigt wird wird benötigt, aber die Linie ist vertikal.

Bei Verwendung des Dreiecks mit Eckpunkten (1,0),(2,1),(1,4)wären die Ausgaben also:

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 

Ich werde versuchen, dies im Laufe der Zeit zu tun, wo und wann ich kann.

Probieren Sie es online! (Ideone)

R. Kap
quelle