Центри трикутника


13

Кола та квадрати мають єдину певну центральну точку. Однак поняття центру трикутника давно обговорюється. Давніх греків були відомі чотири різні центри:

  • Індикатор : перетин бісектрис кута трикутника
  • Центроїд : перетин ліній від кожної вершини трикутника до середини його протилежної сторони
  • Кругоцентр : перетин перпендикулярних бісектрис сторін
  • Ортоцентр : перетин висот трикутника

Пізніше Ейлер довів, що центроїд, циркуляр і ортоцентр є колінеарними в будь-якому трикутнику. Лінія, на якій ці три точки знаходяться в трикутнику, називається лінією Ейлера . Він визначається для кожного трикутника, крім рівностороннього трикутника, де всі точки збігаються.

Ваша задача полягає в тому, щоб створити найкоротшу програму або функцію, яка при двох входах видає певний центр або лінію Ейлера трикутника. Перша вказує координати кожної вершини трикутника. Друге - це ціле число від 1 до 5, визначаючи, що вивести.

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

Ви можете припустити, що дані вершини ніколи не будуть колінеарними, і що вони завжди будуть цілими координатами (це також виключає можливість наявності рівностороннього трикутника як вхідного даних, згідно коментаря @ R.Kap ).

Масив введення повинен бути дійсним вкладеним масивом у вашій мові, а введення має бути у будь-якому розумному форматі. Будь-які значення поплавця повинні відображатися принаймні до 3 знаків після коми, але не менше. Виведена точка повинна бути дійсним масивом вашої мови, що відповідає формату введення.


Тестові приклади:

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

Уточнення: вхід може бути або від stdin, або пробілом, або новим рядком, або як аргументи функції. Однак результат повинен бути записаний у stdout.


1
Я боюся, чіткі формули для центрометра та ортоцентру в декартових координатах досить потворні. Якщо я піду шляхом створення загальних трилінійних / барицентричних => картезіанських координат, стимулювач випадає майже безкоштовно. Див. En.wikipedia.org/wiki/Trilinear_coordinate#Examples . Чи отримую я додаткові бали за його реалізацію?
Джон Дворак

Які допустимі вихідні формати для лінії Ейлера? Якщо вона вертикальна, вона не може бути виражена як y=f(x).
Джон Дворак

1
(будь ласка, прокоментуйте, якщо ви не погоджуєтесь) Будь ласка, використовуйте пісочницю, якщо ви не впевнені, що проблема з вами нормальна чи ні. Там ви можете попросити коментарі та уточнити питання, поки воно не відповідає. Після розміщення тут його не слід змінювати щодо вмісту. Кілька людей, можливо, вже працюють над цим - і не люблять рухомих цілей.
Говард

1
"Виводячи крапку, координати повинні бути ... оточені круглими дужками (())". Чому ця вимога? У деяких мовах точки представлені фігурними дужками. І щось на зразок (12, -2) можна представити лише як рядок, і в цьому випадку самі елементи інтерпретуються як рядки, а не числа.
DavidC

1
Ви можете або хочете зробити це , що вхідні дані можуть бути координати з плаваючою точкою, або повністю позбутися від , (if the triangle is equilateral, output the point at which the centers meet)як це НЕ можливо створити рівносторонній трикутник на координатної площині , використовуючи тільки ціле число координат.
Р. Кап

Відповіді:


2

Пітон - 908 870

Для зменшення прокрутки були додані нові рядки. Це, ймовірно, може бути далі для гольфу.

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

Тестові приклади (анотовано):

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

Як бачите, можливі помилки, викликані використанням плаваючої точки.


Подальше гольф:

На підставі пропозицій в коментарях нижче, мені вдалося зробити це менше.

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
Ви можете зробити щось на кшталт, R=r.appendа потім використати це для збереження байтів?
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
}

Функція може бути мінімізована (приблизно до 600 знаків АБО менше), скорочуючи імена змінних, таких як midx_a, midx_b тощо.

Виклик функції

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

1

Python 3.5, 851 772 байт:

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

Вводить введення як послідовність координат, розділених комами, а потім ціле число, що передає, що виводити. Наприклад, якщо вхідні координати є, (1,0),(2,1),(1,4)і ви хочете ортоцентр трикутника, відповідний цим координатам, ви просто назвете функцію так:

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

Виводиться у форматі кортежу, якщо потрібна конкретна точка, у форматі рядка з рівнянням у формі, y=mx+bякщо потрібна лінія Ейлера, а лінія не вертикальна, або просто xзначення рядка, якщо лінія Ейлера це необхідно , але лінія знаходиться в вертикальному положенні .

Отже, використовуючи трикутник з вершинами (1,0),(2,1),(1,4), виходи будуть:

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 

Я спробую ще більше пограти в гольф, де і коли зможу.

Спробуйте в Інтернеті! (Ідеон)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.