Los centros de un triangulo

13

Los círculos y cuadrados tienen un único punto central definido. Sin embargo, la noción del centro de un triángulo ha sido discutida durante mucho tiempo. Los antiguos griegos conocían cuatro centros diferentes:

  • Incentro : la intersección de las bisectrices angulares del triángulo
  • Centroide : la intersección de las líneas desde cada vértice del triángulo hasta la mitad de su lado opuesto
  • Circuncentro : la intersección de las bisectrices perpendiculares de los lados.
  • Ortocentro : la intersección de las altitudes del triángulo

Euler luego demostró que el centroide, el circuncentro y el ortocentro son colineales en cualquier triángulo. La línea en la que se encuentran estos tres puntos en un triángulo se llama Línea de Euler . Se define para cada triángulo, excepto un triángulo equilátero, donde todos los puntos coinciden.

Su desafío es crear el programa o función más corto que, cuando se le dan dos entradas, emite un centro específico o la línea de Euler del triángulo. El primero especifica las coordenadas de cada vértice de un triángulo. El segundo es un número entero de 1 a 5, que determina qué generar.

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

Puede suponer que los vértices dados nunca serán colineales, y que siempre serán coordenadas enteras (esto también excluye la posibilidad de tener un triángulo equilátero como entrada, según el comentario de @ R.Kap ).

La matriz de entrada debe ser una matriz anidada válida en su idioma, y ​​la entrada debe estar en cualquier formato razonable. Cualquier valor flotante debe mostrarse con al menos 3 decimales, pero no menos. Un punto de salida debe ser una matriz válida en su idioma, que coincida con el formato de entrada.


Casos de prueba:

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

Aclaración: La entrada puede ser desde stdin, espacio o nueva línea separada, o como argumentos para una función. La salida, sin embargo, debe escribirse en stdout.

Volatilidad
fuente
1
Me temo que las fórmulas explícitas para el circuncentro y el ortocentro en coordenadas cartesianas son bastante feas. Si sigo el camino de la creación de coordenadas trilineales / baricéntricas => cartesianas generales, el incentro cae casi libre. Ver en.wikipedia.org/wiki/Trilinear_coordinates#Examples . ¿Recibo puntos extra por implementarlo?
John Dvorak
¿Cuáles son los formatos de salida válidos para la línea Euler? Si es vertical, no se puede expresar como y=f(x).
John Dvorak
1
(comente si no está de acuerdo) Utilice el sandbox si no está seguro de si un desafío está bien o no. Allí puede solicitar comentarios y refinar la pregunta hasta que encaje. Una vez publicado aquí, no se debe cambiar con respecto al contenido. Es posible que varias personas ya trabajen en él, y no les guste mover objetivos.
Howard
1
"Al generar un punto, las coordenadas deben estar ... entre corchetes (())". ¿Por qué este requisito? En algunos idiomas, los puntos se representan entre llaves. Y algo como (12, -2) solo se puede representar como una cadena, en cuyo caso los elementos mismos se interpretan como cadenas en lugar de números.
DavidC
1
Es posible que desee hacer que la entrada pueda ser coordenadas de punto flotante, o deshacerse por completo, (if the triangle is equilateral, output the point at which the centers meet)ya que no es posible crear un triángulo equilátero en el plano de coordenadas utilizando solo coordenadas enteras.
R. Kap

Respuestas:

2

Python - 908 870

Se agregaron nuevas líneas para reducir el desplazamiento. Esto probablemente podría ser más golfizado.

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

Casos de prueba (anotados):

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

Como puede ver, posiblemente haya errores causados ​​por el uso del punto flotante.


Golf adicional:

Según las sugerencias en los comentarios a continuación, he logrado hacer esto más pequeño.

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])
golfista9338
fuente
Creo que en realidad son 907 bytes. (URL acortada).
Erik the Outgolfer
1
¿Podría hacer algo así R=r.appendy luego usarlo para guardar bytes?
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
}

La función se puede minimizar (a unos 600 caracteres O menos) acortando los nombres de las variables como midx_a, midx_b, etc.

Llamando a la función

d:=f([[-2, 0], [1, 0], [0, 1]], 1)
for k,v in d
    msgbox % k "`n" v
Avi
fuente
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])

Toma la entrada como una secuencia de coordenadas separadas por comas seguidas de un número entero que transmite qué generar. Por ejemplo, si las coordenadas de entrada son (1,0),(2,1),(1,4)y desea que el ortocentro del triángulo correspondiente a esas coordenadas simplemente llame a la función de esta manera:

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

Salidas en el formato de una tupla si se necesita un punto específico, en el formato de una cadena con la ecuación en la forma y=mx+bsi se necesita la línea de Euler y la línea no es vertical, o simplemente el xvalor de la línea si la línea de Euler es necesario pero la línea es vertical.

Entonces, usando el triángulo con vértices (1,0),(2,1),(1,4), las salidas serían:

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 

Trataré de jugar más golf con el tiempo donde y cuando pueda.

¡Pruébelo en línea! (Ideona)

R. Kap
fuente