Центры треугольника

13

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

  • Incenter : пересечение угловых биссектрис треугольника
  • Центроид : пересечение линий от каждой вершины треугольника до середины его противоположной стороны
  • Круговой центр : пересечение перпендикулярных биссектрис сторон
  • Ортоцентр : пересечение высот треугольника

Позже Эйлер доказал, что центроид, окружность и ортоцентр коллинеарны в любом треугольнике. Линия, на которой эти три точки находятся в треугольнике, называется линией Эйлера . Он определяется для каждого треугольника, кроме равностороннего треугольника, где все точки совпадают.

Ваша задача - создать самую короткую программу или функцию, которая при наличии двух входов выводит определенный центр или линию Эйлера треугольника. Первый указывает координаты каждой вершины треугольника. Второе - целое число от 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, либо через пробел, либо через новую строку, либо как аргументы функции. Вывод, однако, должен быть записан на стандартный вывод.

летучесть
источник
1
Боюсь, что явные формулы для кругового центра и ортоцентра в декартовых координатах довольно некрасивы. Если я иду по пути создания общих трилинейных / барицентрических => картезианских координат, стимулятор выпадает почти бесплатно. См. En.wikipedia.org/wiki/Trilinear_coordinates#Examples . Получу ли я дополнительные очки за его реализацию?
Джон Дворжак
Каковы допустимые выходные форматы для линии Эйлера? Если он вертикальный, он не может быть выражен как y=f(x).
Джон Дворжак
1
(пожалуйста, прокомментируйте, если вы не согласны) Пожалуйста, используйте песочницу, если вы не уверены, в порядке ли вызов. Там вы можете попросить комментарии и уточнить вопрос, пока он не подходит. После публикации здесь это не должно быть изменено в отношении содержания. Над этим уже могут работать несколько человек - и им не нравятся движущиеся цели.
Говард
1
Msgstr "При выводе точки координаты должны быть ... заключены в круглые скобки (())". Почему это требование? В некоторых языках точки представлены в фигурных скобках. И что-то вроде (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])
golfer9338
источник
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
Avi
источник
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 

Я буду стараться играть в гольф с течением времени, где и когда смогу.

Попробуйте онлайн! (Ideone)

Р. Кап
источник