Les centres d'un triangle

13

Les cercles et les carrés ont un seul point central défini. Cependant, la notion de centre d'un triangle a longtemps été discutée. Quatre centres différents étaient connus des anciens Grecs:

  • Incenter : l'intersection des bissectrices angulaires du triangle
  • Centroïde : l'intersection des lignes de chaque sommet du triangle au milieu de son côté opposé
  • Circumcenter : l'intersection des bissectrices perpendiculaires des côtés
  • Orthocentre : l'intersection des altitudes du triangle

Plus tard, Euler a prouvé que le centroïde, le circumcenter et l'orthocentre sont colinéaires dans n'importe quel triangle. La ligne sur laquelle ces trois points se trouvent dans un triangle est appelée la ligne d'Euler . Il est défini pour chaque triangle sauf un triangle équilatéral, où tous les points coïncident.

Votre défi consiste à créer le programme ou la fonction la plus courte qui, lorsqu'elle reçoit deux entrées, génère un centre spécifique ou la ligne d'Euler du triangle. Le premier spécifie les coordonnées de chaque sommet d'un triangle. Le second est un entier de 1 à 5, déterminant ce qu'il faut sortir.

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

Vous pouvez supposer que les sommets donnés ne seront jamais colinéaires et qu'ils seront toujours des coordonnées entières (cela exclut également la possibilité d'avoir un triangle équilatéral en entrée, conformément au commentaire de @ R.Kap ).

Le tableau d'entrée doit être un tableau imbriqué valide dans votre langue et l'entrée doit être dans un format raisonnable. Toutes les valeurs flottantes doivent être affichées à au moins 3 décimales, mais pas moins. Un point en sortie doit être un tableau valide dans votre langue, correspondant au format d'entrée.


Cas de 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

Clarification: L'entrée peut provenir de stdin, être séparée par des espaces ou des nouvelles lignes, ou comme arguments d'une fonction. Cependant, la sortie doit être écrite sur stdout.

Volatilité
la source
1
Je crains que les formules explicites pour le circumcenter et l'orthocentre en coordonnées cartésiennes soient assez laides. Si je vais dans le sens de la création d'une coordonnée trilinéaire / barycentrique => carthésienne générale, l'incitatif abandonne presque gratuitement. Voir en.wikipedia.org/wiki/Trilinear_coordinates#Examples . Puis-je obtenir des points supplémentaires pour sa mise en œuvre?
John Dvorak
Quels sont les formats de sortie valides pour la ligne Euler? S'il est vertical, il ne peut pas être exprimé comme y=f(x).
John Dvorak
1
(Veuillez commenter si vous n'êtes pas d'accord) Veuillez utiliser le bac à sable si vous n'êtes pas sûr qu'un défi soit correct ou non. Là, vous pouvez demander des commentaires et affiner la question jusqu'à ce qu'elle corresponde. Une fois publié ici, il ne devrait pas être modifié en ce qui concerne le contenu. Plusieurs personnes pourraient déjà y travailler - et n'aiment pas déplacer des cibles.
Howard
1
Msgstr "Lors de la sortie d 'un point, les coordonnées doivent être ... entourées entre crochets (())". Pourquoi cette exigence? Dans certaines langues, les points sont représentés entre crochets. Et quelque chose comme (12, -2) ne peut être représenté que sous forme de chaîne, auquel cas les éléments eux-mêmes sont interprétés comme des chaînes plutôt que des nombres.
DavidC
1
Vous pouvez soit faire en sorte que l'entrée puisse être des coordonnées à virgule flottante, soit vous en débarrasser complètement (if the triangle is equilateral, output the point at which the centers meet)car il n'est pas possible de créer un triangle équilatéral sur le plan de coordonnées en utilisant uniquement des coordonnées entières.
R. Kap

Réponses:

2

Python - 908 870

De nouvelles lignes ont été ajoutées pour réduire le défilement. Cela pourrait probablement être joué plus loin.

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

Cas de test (annotés):

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

Comme vous pouvez le voir, il peut y avoir des erreurs causées par l'utilisation de virgule flottante.


Golf:

Sur la base des suggestions dans les commentaires ci-dessous, j'ai réussi à le réduire.

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])
golfeur9338
la source
Je pense que c'est en fait 907 octets. (URL raccourcie).
Erik the Outgolfer le
1
Pourriez-vous faire quelque chose comme ça R=r.appendet ensuite l'utiliser tout au long pour économiser des octets?
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 fonction peut être plus réduite (à environ 600 caractères OU moins) en raccourcissant les noms de variables comme midx_a, midx_b et ainsi.

Appel de la fonction

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

Python 3.5, 851 772 octets:

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

Prend l' entrée sous la forme d'une séquence de coordonnées séparées par des virgules suivie d'un entier indiquant ce qui doit être sorti. Par exemple, si les coordonnées d'entrée sont (1,0),(2,1),(1,4)et que vous voulez que l'orthocentre du triangle correspondant à ces coordonnées, vous appelez simplement la fonction comme suit:

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

Sorties au format d'un tuple si un point spécifique est nécessaire, au format d'une chaîne avec l'équation sous la forme y=mx+bsi la ligne Euler est nécessaire et la ligne n'est pas verticale, ou simplement la xvaleur de la ligne si la ligne Euler est nécessaire mais la ligne est verticale.

Donc, en utilisant le triangle avec des sommets (1,0),(2,1),(1,4), les sorties seraient:

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 

J'essaierai de jouer au golf au fil du temps où et quand je le pourrai.

Essayez-le en ligne! (Ideone)

R. Kap
la source