Bir üçgenin merkezleri


13

Daireler ve karelerin tek, kesin bir merkez noktası vardır. Bununla birlikte, bir üçgen merkezi kavramı uzun zamandır tartışılmaktadır. Eski Yunanlılar tarafından dört farklı merkez biliniyordu:

  • Incenter : Üçgenin açılı açıortaylarının kesişimi
  • Centroid : Üçgenin her köşesinden çizgilerin karşı tarafının ortasına doğru kesişimi
  • Daire : Yanların dik açıortaylarının kesişimi
  • Ortoenter : Üçgenin rakımlarının kesişimi

Euler daha sonra centroid, circumcenter ve ortocenter'ın herhangi bir üçgende eşdoğrusal olduğunu kanıtladı. Bu üç noktanın bir üçgen içinde bulunduğu çizgiye Euler Hattı denir . Tüm noktaların çakıştığı eşkenar üçgen hariç her üçgen için tanımlanmıştır.

Zorluğunuz, iki giriş verildiğinde, belirli bir merkez veya üçgenin Euler Çizgisini çıktı veren en kısa program veya işlevi oluşturmaktır. Birincisi, bir üçgenin her bir tepe noktasının koordinatlarını belirtir. İkincisi, ne çıkacağını belirleyen 1 ila 5 arasında bir tam sayıdır.

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

Verilen köşelerin hiçbir zaman eş zamanlı olmayacağını ve her zaman tamsayı koordinatları olacağını varsayabilirsiniz (bu aynı zamanda @ R.Kap'ın yorumuna göre giriş olarak eşkenar üçgen olması olasılığını da hariç tutar ).

Giriş dizisi, dilinizde geçerli bir iç içe dizidir ve girdi makul bir biçimde olmalıdır. Herhangi bir kayan nokta değeri en az 3 ondalık basamağa gösterilmelidir, ancak daha az olmamalıdır. Çıkarılan bir nokta, giriş biçimiyle eşleşen, dilinizde geçerli bir dizi olmalıdır.


Test senaryoları:

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

Açıklama: Girdi stdin'den, boşluktan veya yeni satırdan ayrılmış olarak ya da bir işleve argümanlar olarak olabilir. Ancak çıktı stdout'a yazılmalıdır.


1
Korkarım kartezyen koordinatlarda çember ve ortoenter için açık formüller oldukça çirkin. Genel üçgensel / barycentric => carthesian koordinatları yaratmanın yoluna gidersem, teşvikçi neredeyse serbest kalıyor. Bkz. En.wikipedia.org/wiki/Trilinear_coordinates#Examples . Uygulamak için ekstra puan alır mıyım?
John Dvorak

Euler hattı için geçerli çıktı biçimleri nelerdir? Dikey ise, olarak ifade edilemez y=f(x).
John Dvorak

1
(Eğer katılmıyorsanız yorum yapın) Eğer bir meydan okuma olup olmadığından emin değilseniz lütfen korumalı alanı kullanın . Orada yorum isteyebilir ve uygun olana kadar soruyu hassaslaştırabilirsiniz. Buraya gönderildikten sonra içerik bakımından değiştirilmemelidir. Birkaç kişi zaten üzerinde çalışabilir ve hareketli hedefleri sevmez.
Howard

1
Msgstr "Bir nokta çıkarırken, koordinatlar ... yuvarlak parantez (()) içine alınmalıdır". Neden bu gereklilik? Bazı dillerde, noktalar süslü parantez içinde gösterilir. Ve (12, -2) gibi bir şey sadece bir dize olarak temsil edilebilir, bu durumda elemanların kendileri sayılardan ziyade dize olarak yorumlanır.
DavidC

1
Ya giriş kayan nokta koordinatları, ya da tamamen kurtulabilirsiniz o yapmak isteyebilirsiniz (if the triangle is equilateral, output the point at which the centers meet)olduğu gibi değil sadece koordinatlar tam sayı kullanılarak koordinat düzleminde bir eşkenar üçgen oluşturmak mümkündür.
R. Kap

Yanıtlar:


2

Python - 908 870

Kaydırmayı azaltmak için yeni satırlar eklendi. Bu muhtemelen daha fazla golf olabilir.

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

Test senaryoları (açıklamalı):

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

Gördüğünüz gibi, kayan nokta kullanmanın neden olduğu hatalar olabilir.


Daha fazla golf:

Aşağıdaki yorumlardaki önerilere dayanarak, bunu daha küçük yapmayı başardım.

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
Gibi bir şey yapabilir R=r.appendve daha sonra bayt kurtarmak için bunu kullanabilirsiniz?
FlipTack

1

Otomatik Kısayol - 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
}

İşlev, midx_a, midx_b ve benzeri gibi değişken adlarını kısaltarak daha da küçültülebilir (yaklaşık 600 karakter veya daha az).

İşlevin çağrılması

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

1

Python 3,5, 851 772 bayt:

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

Alır giriş çıkışına ne taşıyan bir tamsayı ve ardından virgülle ayrılmış koordinatlarının bir dizi olarak. Örneğin, giriş koordinatları ise (1,0),(2,1),(1,4)ve üçgenin orkenterinin bu koordinatlara karşılık gelmesini istiyorsanız, işlevi şöyle çağırmanız yeterlidir:

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

Çıkışlar tuple biçiminde belirli bir noktaya formunda denklemle bir dizi formatında, gerekirse y=mx+bEuler doğrusu gerekli olup olmadığını ve çizgi olup , dikey ya da sadece xsatır Euler doğrusu eğer değeri gerekli ama çizgi olduğunu dikey.

Köşeleri olan üçgeni kullanarak (1,0),(2,1),(1,4)çıktılar şöyle olur:

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 

Nerede ve ne zaman yapabileceğim zaman içinde bu daha golf çalışacağız.

Çevrimiçi Deneyin! (Ideone)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.