Środki trójkąta

13

Koła i kwadraty mają jeden określony punkt środkowy. Jednak pojęcie środka trójkąta było długo dyskutowane. Starożytni Grecy znali cztery różne ośrodki:

  • Incenter : Przecięcie bisectors kąta trójkąta
  • Środek ciężkości : Przecięcie linii od każdego wierzchołka trójkąta do środka jego przeciwnej strony
  • Circumcenter : Przecięcie prostopadłych dwusiecznych boków
  • Ortocentrum : Przecięcie wysokości trójkąta

Później Euler udowodnił, że środek ciężkości, środek okręgu i ortocentrum są współliniowe w dowolnym trójkącie. Linia, na której te trzy punkty znajdują się w trójkącie, nazywa się linią Eulera . Jest on zdefiniowany dla każdego trójkąta oprócz trójkąta równobocznego, w którym wszystkie punkty pokrywają się.

Wyzwanie polega na stworzeniu najkrótszego programu lub funkcji, która przy dwóch wejściach generuje określone centrum lub linię Eulera trójkąta. Pierwszy określa współrzędne każdego wierzchołka trójkąta. Druga to liczba całkowita od 1 do 5, określająca, co wyprowadzić.

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

Możesz założyć, że podane wierzchołki nigdy nie będą współliniowe, i że zawsze będą to współrzędne całkowite (wyklucza to również możliwość wprowadzenia trójkąta równobocznego jako danych wejściowych, zgodnie z komentarzem @ R.Kapa ).

Tablica wejściowa powinna być prawidłową tablicą zagnieżdżoną w Twoim języku, a dane wejściowe powinny mieć dowolny rozsądny format. Wszelkie wartości zmiennoprzecinkowe powinny być wyświetlane z co najmniej 3 miejscami po przecinku, ale nie mniej. Punktem wyjściowym powinna być poprawna tablica w twoim języku, zgodna z formatem wejściowym.


Przypadki testowe:

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

Wyjaśnienie: Dane wejściowe mogą pochodzić ze standardowego wejścia, oddzielone spacją lub znakiem nowej linii lub jako argumenty funkcji. Dane wyjściowe należy jednak zapisać na standardowe wyjście.

Zmienność
źródło
1
Obawiam się, że wyraźne wzory na środek okręgu i ortocentrum we współrzędnych kartezjańskich są dość brzydkie. Jeśli pójdę drogą tworzenia ogólnych współrzędnych trójliniowych / barycentrycznych => kartezjańskich, wgłębienie wypadnie prawie całkowicie. Zobacz en.wikipedia.org/wiki/Trilinear_coordinates#Examples . Czy dostaję dodatkowe punkty za wdrożenie?
John Dvorak,
Jakie są prawidłowe formaty wyjściowe dla linii Eulera? Jeśli jest pionowy, nie można go wyrazić jako y=f(x).
John Dvorak,
1
(prosimy o komentarz, jeśli się nie zgadzasz) Proszę użyć piaskownicy, jeśli nie jesteś pewien, czy wyzwanie jest w porządku, czy nie. Tam możesz poprosić o komentarz i dopracować pytanie, aż będzie pasować. Po opublikowaniu tutaj nie należy go zmieniać w odniesieniu do treści. Kilka osób może już nad tym pracować - i nie lubią przesuwać celów.
Howard
1
„Podczas wysyłania punktu współrzędne muszą być ... otoczone nawiasami okrągłymi (())”. Dlaczego ten wymóg? W niektórych językach punkty są reprezentowane w nawiasach klamrowych. I coś w rodzaju (12, -2) może być reprezentowane tylko jako ciąg, w którym to przypadku same elementy są interpretowane jako ciągi, a nie liczby.
DavidC
1
Można też chcemy, aby było to wejście może być pływające Współrzędne punktu, lub całkowicie pozbyć (if the triangle is equilateral, output the point at which the centers meet), ponieważ jest to nie możliwe, aby tworzyć trójkąt równoboczny na płaszczyźnie współrzędnych przy użyciu tylko całkowitą współrzędnych.
R. Kap

Odpowiedzi:

2

Python - 908 870

Dodano nowe linie, aby ograniczyć przewijanie. Prawdopodobnie można by dalej grać w golfa.

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

Przypadki testowe (z przypisami):

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

Jak widać, możliwe są błędy spowodowane przez użycie zmiennoprzecinkowe.


Dalsza gra w golfa:

W oparciu o sugestie w komentarzach poniżej udało mi się to zmniejszyć.

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
źródło
Myślę, że to właściwie 907 bajtów. (URL skrócony).
Erik the Outgolfer
1
Czy możesz zrobić coś podobnego, R=r.appenda następnie wykorzystać to przez cały czas, aby zaoszczędzić bajty?
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
}

Funkcja może być bardziej zminimalizowana (do około 600 znaków LUB mniej) poprzez skrócenie nazw zmiennych, takich jak midx_a, midx_b i tak dalej.

Wywołanie funkcji

d:=f([[-2, 0], [1, 0], [0, 1]], 1)
for k,v in d
    msgbox % k "`n" v
Avi
źródło
1

Python 3.5, 851 772 bajtów:

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

Pobiera dane wejściowe jako ciąg współrzędnych oddzielonych przecinkami, po których następuje liczba całkowita przenosząca dane wyjściowe. Na przykład, jeśli współrzędne wejściowe są (1,0),(2,1),(1,4)i chcesz, aby ortocentrum trójkąta odpowiadało tym współrzędnym, po prostu wywołaj funkcję w następujący sposób:

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

Dane wyjściowe są w formacie krotki, jeśli potrzebny jest określony punkt, w formacie ciągu znaków z równaniem w postaci, y=mx+bjeśli potrzebna jest linia Eulera, a linia nie jest pionowa, lub po prostu xwartość linii, jeśli linia Eulera jest potrzebne, ale linia jest pionowa.

Tak więc, używając trójkąta z wierzchołkami (1,0),(2,1),(1,4), wyniki byłyby następujące:

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 

Z czasem spróbuję zagrać w golfa, gdzie i kiedy będę mógł.

Wypróbuj online! (Ideone)

R. Kap
źródło