I centri di un triangolo


13

I cerchi e i quadrati hanno un unico, preciso punto centrale. Tuttavia, la nozione del centro di un triangolo è stata a lungo discussa. Quattro diversi centri erano noti agli antichi greci:

  • Incentore : l'intersezione delle bisettrici angolari del triangolo
  • Centroide : l'intersezione delle linee da ciascun vertice del triangolo al centro del lato opposto
  • Circoncentro : l'intersezione delle bisettrici perpendicolari dei lati
  • Orthocenter : l'intersezione delle altitudini del triangolo

Eulero in seguito ha dimostrato che il centroide, il circoncenter e l'ortocentro sono collineari in qualsiasi triangolo. La linea su cui si trovano questi tre punti in un triangolo è chiamata Linea di Eulero . È definito per ogni triangolo tranne un triangolo equilatero, in cui tutti i punti coincidono.

La tua sfida è quella di creare il programma o la funzione più breve che, quando vengono dati due ingressi, genera un centro specifico o la Linea di Eulero del triangolo. Il primo specifica le coordinate di ciascun vertice di un triangolo. Il secondo è un numero intero compreso tra 1 e 5, che determina cosa emettere.

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

Puoi presumere che i vertici dati non saranno mai collineari e che saranno sempre coordinate intere (questo esclude anche la possibilità di avere un triangolo equilatero come input, come da commento di @ R.Kap ).

L'array di input deve essere un array nidificato valido nella tua lingua e l'input deve essere in qualsiasi formato ragionevole. Tutti i valori float devono essere visualizzati con almeno 3 cifre decimali, ma non meno. Un punto emesso dovrebbe essere un array valido nella tua lingua, corrispondente al formato di input.


Casi test:

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

Chiarimento: l'input può provenire da stdin, separato da spazio o da nuova riga, oppure come argomento di una funzione. L'output, tuttavia, deve essere scritto su stdout.


1
Temo che formule esplicite per il circumcenter e l'ortocentro nelle coordinate cartesiane siano piuttosto brutte. Se avrò il modo di creare un generale trilineare / baricentriche => coordinate cartesiane, l'incentro cadrà quasi libero. Vedi en.wikipedia.org/wiki/Trilinear_coordinates#Examples . Ricevo punti extra per implementarlo?
John Dvorak,

Quali sono i formati di output validi per la linea Euler? Se è verticale, non può essere espresso come y=f(x).
John Dvorak,

1
(si prega di commentare se non si è d'accordo) Si prega di utilizzare la sandbox se non si è sicuri se una sfida è ok o no. Lì puoi chiedere commenti e perfezionare la domanda fino a quando non si adatta. Una volta pubblicato qui non dovrebbe essere modificato per quanto riguarda il contenuto. Diverse persone potrebbero già lavorarci sopra e non amano spostare obiettivi.
Howard,

1
"Quando si emette un punto, le coordinate devono essere ... racchiuse tra parentesi tonde (())". Perché questo requisito? In alcune lingue, i punti sono rappresentati tra parentesi graffe. E qualcosa come (12, -2) può essere rappresentato solo come una stringa, nel qual caso gli elementi stessi vengono interpretati come stringhe piuttosto che numeri.
DavidC,

1
Si può sia vuole fare in modo che l'ingresso può essere coordinate in virgola mobile, o completamente sbarazzarsi di (if the triangle is equilateral, output the point at which the centers meet)come è non possibile creare un triangolo equilatero sul piano delle coordinate usando solo numeri interi coordinate.
R. Kap,

Risposte:


2

Python - 908 870

Sono state aggiunte nuove linee per ridurre lo scorrimento. Questo potrebbe probabilmente essere ulteriormente approfondito.

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

Casi di prova (annotati):

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

Come puoi vedere, ci sono probabilmente errori causati dall'uso del virgola mobile.


Ulteriore golf:

Sulla base dei suggerimenti nei commenti seguenti, sono riuscito a ridurlo.

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
Potresti fare qualcosa del genere R=r.appende poi usarlo per salvare byte?
FlipTack

1

Tasto di scelta automatica - 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
}

La funzione può essere più ridotta (a circa 600 caratteri o meno) accorciando i nomi delle variabili come midx_a, midx_b e così via.

Chiamata alla funzione

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

1

Python 3.5, 851 772 byte:

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

Prende l' input come una sequenza di coordinate separate da virgola seguita da un numero intero che trasmette cosa emettere. Ad esempio, se le coordinate di input sono (1,0),(2,1),(1,4)e vuoi che l'ortocentro del triangolo corrisponda a quelle coordinate, chiameresti semplicemente la funzione in questo modo:

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

Emette nel formato di una tupla se è necessario un punto specifico, nel formato di una stringa con l'equazione nella forma y=mx+bse è necessaria la linea di Eulero e la linea non è verticale, o semplicemente il xvalore della linea se la linea di Eulero è necessario ma la linea è verticale.

Quindi, usando il triangolo con i vertici (1,0),(2,1),(1,4), le uscite sarebbero:

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 

Proverò a giocare a golf più nel tempo dove e quando posso.

Provalo online! (Ideone)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.