Os centros de um triângulo


13

Círculos e quadrados têm um ponto central único e definido. No entanto, a noção do centro de um triângulo tem sido discutida há muito tempo. Quatro centros diferentes eram conhecidos pelos gregos antigos:

  • Incentivo : a interseção dos bissetores de ângulos do triângulo
  • Centroid : A interseção das linhas de cada vértice do triângulo até o meio do seu lado oposto
  • Circuncentro : A interseção dos bissetores perpendiculares dos lados
  • Orthocentro : A interseção das altitudes do triângulo

Euler mais tarde provou que o centróide, o circuncentro e o ortocentro são colineares em qualquer triângulo. A linha em que esses três pontos estão em um triângulo é chamada de Linha de Euler . É definido para cada triângulo, exceto um triângulo equilátero, onde todos os pontos coincidem.

Seu desafio é criar o programa ou função mais curto que, quando recebidas duas entradas, gera um centro específico ou a linha Euler do triângulo. O primeiro especifica as coordenadas de cada vértice de um triângulo. O segundo é um número inteiro de 1 a 5, determinando o que produzir.

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

Você pode supor que os vértices fornecidos nunca serão colineares e que sempre serão coordenadas inteiras (isso também exclui a possibilidade de ter um triângulo equilátero como entrada, conforme comentário de @ R.Kap ).

A matriz de entrada deve ser uma matriz aninhada válida no seu idioma e a entrada deve estar em qualquer formato razoável. Quaisquer valores flutuantes devem ser exibidos com pelo menos três casas decimais, mas não menos. Um ponto de saída deve ser uma matriz válida no seu idioma, correspondente ao formato de entrada.


Casos de teste:

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

Esclarecimento: A entrada pode ser de stdin, separada por espaço ou nova linha, ou como argumentos para uma função. A saída, no entanto, deve ser gravada em stdout.


1
Receio que fórmulas explícitas para o circuncentro e o ortocentro nas coordenadas cartesianas sejam bastante feias. Se eu for o caminho da criação de coordenadas gerais trilineares / baricêntricas => cartesianas, o incentor cai quase de graça. Consulte en.wikipedia.org/wiki/Trilinear_coordinates#Examples . Recebo pontos extras por implementá-lo?
John Dvorak

Quais são os formatos de saída válidos para a linha Euler? Se for vertical, não poderá ser expresso como y=f(x).
John Dvorak

1
(por favor, comente se não concorda) Por favor, use a caixa de areia se não tiver certeza se um desafio está correto ou não. Lá, você pode pedir comentários e refinar a pergunta até que ela se encaixe. Uma vez publicado aqui, não deve ser alterado com relação ao conteúdo. Várias pessoas já podem trabalhar nisso - e não gostam de mover alvos.
257 Howard

1
"Ao emitir um ponto, as coordenadas devem estar ... entre colchetes (())". Por que esse requisito? Em alguns idiomas, os pontos são representados entre colchetes. E algo como (12, -2) só pode ser representado como uma sequência, caso em que os próprios elementos são interpretados como sequências em vez de números.
25413 DavidC

1
Você pode tanto deseja torná-lo que a entrada pode ser flutuantes coordenadas do ponto, ou completamente se livrar de (if the triangle is equilateral, output the point at which the centers meet)uma vez que é não possível criar um triângulo equilátero no plano de coordenadas utilizando apenas inteiro coordenadas.
R. Kap 23/05

Respostas:


2

Python - 908 870

Novas linhas foram adicionadas para reduzir a rolagem. Provavelmente isso poderia ser ainda mais jogado.

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 teste (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 você pode ver, possivelmente há erros causados ​​pelo uso do ponto flutuante.


Golfe adicional:

Com base nas sugestões dos comentários abaixo, eu consegui fazer isso menor.

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
Você poderia fazer algo assim R=r.appende depois usá-lo para salvar 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
}

A função pode ser mais minificada (para cerca de 600 caracteres OU menos) encurtando os nomes de variáveis ​​como midx_a, midx_b e assim por diante.

Chamando a função

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

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

Recebe a entrada como uma sequência de coordenadas separadas por vírgula, seguidas por um número inteiro que transmite o que deve ser produzido. Por exemplo, se as coordenadas de entrada são (1,0),(2,1),(1,4)e você deseja o ortocentro do triângulo correspondente a essas coordenadas, você simplesmente chamaria a função da seguinte maneira:

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

Saídas no formato de uma tupla, se for necessário um ponto específico, no formato de uma string com a equação no formulário, y=mx+bse a linha de Euler for necessária e a linha não for vertical, ou simplesmente o xvalor da linha, se a linha de Euler é necessário, mas a linha é vertical.

Portanto, usando o triângulo com vértices (1,0),(2,1),(1,4), as saídas seriam:

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 

Vou tentar jogar isso mais ao longo do tempo, onde e quando puder.

Experimente Online! (Ideona)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.