Noktanın üçgenin içinde olup olmadığını kontrol edin


40

Amacınız, verilen 2B noktasının X, verilen A, B, C köşeleriyle üçgen alanı içinde olup olmadığını belirlemektir.

Test noktası X'in koordinatlarında ve üçgenin köşelerinde (toplamda 8 koordinat olmak üzere) alan ve nokta bu üçgenin içinde yer alıyorsa True, dışında ise False döndüren bir işlev yazın.

Kenar davaları için endişelenme. Nokta üçgenin sınırındaysa (kenar veya tepe) veya üçgen aslında bir çizgi parçasıysa, kodunuz çökme de dahil olmak üzere herhangi bir şeyi yapabilir. Ayrıca sayısal stabilite veya kayan nokta hassasiyeti konusunda endişelenmeyin.

Kodunuz adlandırılmış bir fonksiyon olmalıdır. Kod parçacıkları kabul edilmeyecek.

En az karakter kazanır.

Giriş:

Koordinatları temsil eden sekiz gerçek sayı. Sayılar aralıkta olacak (-1,1).

Tam giriş formatı esnektir. Örneğin, sekiz sayı, sekiz sayı listesi, her biri bir demet tarafından verilen dört nokta listesi, 2 * 4 matris, dört karmaşık sayı, iki x-koordinatı listesi ve y koordinatı alabilir. ve bunun gibi.

Girdi yalnızca ek kapsayıcı olmayan bazı kaptaki sayılar olmalıdır. Girdiyi herhangi bir ön işleme yapmak için kullanamazsınız, ya da artan y koordinatlarında verilen noktaların belirtilmesi gibi girdi üzerinde herhangi bir kısıtlama gerektirmezsiniz. Girişiniz herhangi bir sekiz koordinat için izin vermelidir (kodunuz daha önce bahsedilen son durumlarda keyfi davranabilir).

Lütfen giriş biçiminizi belirtin.

Çıktı:

İlgili Boole True/ False, karşılık gelen sayı 1/ 0veya dilinizdeki analoglar.

Test durumları

Girdilerde [X,A,B,C]dört tupe, önce test noktası, ardından üç üçgen köşeleri içeren bir liste verilir . Onları çıktıları olması gerekenler Trueve olması gerekenler olarak gruplandırdım False.

True örneklerini:

[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]

False örneklerini:

[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]

Bir karakter tanımınız nedir? Ascii? 7 bitte kodlanabilir mi? Baytta mı? Unicode var mı?
isaacg

Sen ne önerirsin? Sıkıştırılmış kod kullanan çözümler zaten var.
xnor

Genelde, baytların Ascii olmayan karakterler için kullanıldığına inanıyorum, çünkü aksi takdirde Utf-32 avantajı aşılmazdır.
isaacg

Şey, şimdi geri dönemem; Herhangi bir Unicode karakteri bir karakterdir. İstersen sıkıştır.
xnor

Yanıtlar:


19

Javascript / ECMAScript 6, 161 159 158/152

JavaScript:

function $(t,r,i,a,n,g,l,e){b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

ECMAScript 6 versiyonu (teşekkürler m.buettner, 6 karakter kaydeder)

$=(t,r,i,a,n,g,l,e)=>{b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

Buna şöyle diyoruz (döner trueveya false):

$(pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y);

Bu cevabın koduna dayanarak bazı süslü baryentrik koordinat matematik kullanır . Okuma zevkiniz için ağzı açılmış bir versiyon aşağıdaki gibidir:

function $ (pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y) {
  var A =  (-v2Y * v3X + v1Y * (-v2X + v3X) + v1X * (v2Y - v3Y) + v2X * v3Y) / 2;
  var sign = A < 0 ? -1 : 1;
  var s = (v1Y * v3X - v1X * v3Y + (v3Y - v1Y) * pointX + (v1X - v3X) * pointY) * sign;
  var t = (v1X * v2Y - v1Y * v2X + (v1Y - v2Y) * pointX + (v2X - v1X) * pointY) * sign;
  return s > 0 && t > 0 && s + t < 2 * A * sign;
}

12
+1, sadece parametre isimleri için!
Matt

Neden benim karakter sayma UserScript kırmak zorundasın ???
kitcar2000

@ kitcar2000 ne demek istiyorsun?
Abraham,

Kurallar karakterlerin bayt sayıldığını söylüyor. Yani bunu kullanabilirsiniz: xem.github.io/obfuscatweet 122 karaktere sığdırmak için
xem

1
Yanılıyor muyum yoksa (a*(l-n)+i*(g-e)+n*e-g*l)yerine kullanabilir miydin (-g*l+a*(-n+l)+i*(g-e)+n*e)?
Zacharý

19

Python 2.7 128 127 117 110 109 103 99 95 94 91 90

İlk kod golf denemem!

kod

f=lambda x,y,t:sum(a*y+c*b+d*x<d*a+c*y+b*x for i in(0,1,2)for a,b,c,d in[t[i-1]+t[i]])%3<1

(X, y, t) girişini alır; burada (x, y) kontrol ettiğimiz noktadır ve t, bir üçgen = t (((x1, y1), (x2, y2), (x3, y3))).

açıklama

Matrislerin belirleyicilerini hesaplıyorum

| 1 x1 y1 |      | 1 x2 y2 |      | 1 x3 y3 |
| 1 x2 y2 | ,    | 1 x3 y3 | ,    | 1 x1 y1 | .
| 1 x  y  |      | 1 x  y  |      | 1 x  y  |

Bu belirleyiciler, üçgenin kenarlarından noktaya (x, y) işaretli mesafeleri temsil eder. Hepsi aynı işarete sahipse, nokta her çizginin aynı tarafındadır ve bu nedenle üçgen içinde bulunur.

Yukarıdaki kodda a*y+c*b+d*x-d*a-c*y-b*x, bu matrislerden birinin belirleyicisidir.

Ben gerçeği kullanıyorum True+True+True==3ve False+False+False==0bu belirleyicileri hepsi aynı işarete sahip olmadığını belirlemek için.

Python'un negatif liste endekslerini kullanmak t[-1]yerine kullanırım t[(i+1)%3].

S, 0 veya 3 olup olmadığını kontrol etmek s%3<1yerine kullanmak için fikir için teşekkürler Peter s in(0,3)!

Sagemath Sürümü

Gerçekten farklı bir çözüm değil, bu yüzden ben bu cevaba, 80 karakter kullanan bir sagemath çözümüne katılıyorum :

f=lambda p,t,o=[1]:sum([det(Matrix([o+t[i-1],o+t[i],o+p]))<0for i in 0,1,2])%3<1

nerede p=[x,y]vet=[[x1,y1],[x2,y2],[x3,y3]]


1
Could s in (0,3)için kısaltılabilir s%3<1?
Peter Taylor

1
Negatif endekslerin kullanımı bir tane daha kazanmak için ince ayarlanabilir: -1,0,1 ... t[i]+t[i+1]eşittir0,1,2 ... t[i-1]+t[i]
Peter Taylor

@PeterTaylor Kesinlikle doğru! Çok kötü, bunu in -1,0,1okumadan önce bu boşluğu kaldırdım . Aslında senin yolun daha okunaklı, bu yüzden yine de kullanacağım.
Alex L

1
Golf koduna hoş geldiniz! Parantezleri içine sumalıyorsanız 0,1,2içindeki boşlukların yerine getirilmesi durumunda karakter kavrama için köşeli parantezlerden kurtulabilirsiniz . Bunun nedeni, Python'un işlevsiz bir şekilde kavranmasının işlevlere aktarılmasına izin vermesidir, ancak çıplak gruptaki virgüller 1,2,3onu karıştırır çünkü onları ayrı argümanlar olarak ayrıştırmaya çalışır.
xnor

16

Mathematica, 67 bayt

f=Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])&

İşlev, sırasıyla ve olarak adlandırılan iki argümanı, noktayı Xve noktaların listesini alır . Eğer ararsan{A,B,C}##2

f[X,{A,B,C}]

o zaman alırsınız #olarak Xve #2sıra {A,B,C}. (Kodun içine yerleştirilmiş diğer iki anonim işlev olduğunu unutmayın - #ve #2bunların içinde farklı bir anlamı vardır.)

İşte fonksiyonun bir açıklaması:

                                              x=#;#2            & (* Save X into a variable x, but evaluate to {A,B,C}. *)
                                    Partition[x=#;#2,2,1,{1,1}] & (* Get a cyclic list of pairs {{A,B},{B,C},{C,B}}. *)
       (                        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Define an anonymous function and apply it to each 
                                                                     of the above pairs. The two elements are referred 
                                                                     to as # and #2. *)
       (          (#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Subtract the two points. For a pair of vertices 
                                                                     this yields a vector corresponding to the edge 
                                                                     between them. *)
        {#2,-#}&                                                  (* An anonymous function that takes two values, 
                                                                     reverses them, inverts the sign of one of them 
                                                                     and puts them into a list. *)
       ({#2,-#}&@@(#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Applied to the edge, this yields its normal. *)
       ({#2,-#}&@@(#-#2).(x-#)  &@@@Partition[x=#;#2,2,1,{1,1}])& (* Take the scalar product of that normal with a
                                                                     vector from a vertex to x. This is projection of 
                                                                     this vector onto that normal and hence the SIGNED
                                                                     distance of x from the edge. *)
       ({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check the sign of that distance, the exact mapping 
                                                                     between (left, right) and (True, False) is 
                                                                     irrelevant, as long as it's consistent. *)
Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check if all signs are equal - that is, if point X 
                                                                     lies on the same side of all edges. This is 
                                                                     equivalent to check that the point is inside the 
                                                                     triangle. *)

Bu fonksiyonun , köşeleri saat yönünde veya saat yönünün tersi sırayla verilmiş olduğu sürece , aslında herhangi bir dışbükey için işe yarayacağını unutmayın .


Mesafelerin ürününün tüm işaretlerin eşit olduğundan daha olumlu olup olmadığını kontrol etmek daha etkili olmaz mıydı? Ben Mathematica'lı değilim, ama sanırım daha kolay olmalı.
isaacg

@isaacg Üç terim vardır, bu nedenle hepsi olumsuzsa, ürünleri olumsuzdur ve hepsi olumluysa, ürünleri olumludur. Yaklaşımınız yalnızca iki sayının işareti eşit olduğunda çalışır.
Martin Ender,

Neden kullanmaz Det?
alephalpha

@alephalpha Eh, muhtemelen düşünmedim çünkü. : P ... Şuna bakacağım
Martin Ender

@alephalpha Hm hayır, şu anda gerekli üç matrisi daha az karakterde oluşturmanın bir yolunu bulamıyorum.
Martin Ender

7

CJam, 66 63 59 52 46 34 32 31 30 28 karakter

"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

Unicode dizesini dönüştürdükten sonra, aşağıdaki kod ( 33 bayt ) değerlendirilir:

{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T

X [A B C]Her noktanın formda olduğu girdi olarak beklenir [double double]. Çıkış 1 veya 0.

Çevrimiçi deneyin.

Büyük bir teşekkür, 6 karakter (13 bayt sıkıştırılmamış kod) kaydetmek için user23013'e gider !

Test durumları

$ cat triangle.cjam
"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

[
  [-0.31961 -0.12646] [ [0.38478 0.37419]   [-0.30613 -0.59754] [-0.85548 0.6633]   ] T
  [-0.87427 -0.00831] [ [0.78829 0.60409]   [-0.90904 -0.13856] [-0.80685 0.48468]  ] T
  [0.28997 -0.03668]  [ [-0.28362 0.42831]  [0.39332 -0.07474]  [-0.48694 -0.10497] ] T
  [-0.07783 0.04415]  [ [-0.34355 -0.07161] [0.59105 -0.93145]  [0.29402 0.90334]   ] T
  [0.36107 0.05389]   [ [0.27103 0.47754]   [-0.00341 -0.79472] [0.82549 -0.29028]  ] T
  [-0.01655 -0.20437] [ [-0.36194 -0.90281] [-0.26515 -0.4172]  [0.36181 0.51683]   ] T
  [-0.12198 -0.45897] [ [-0.35128 -0.85405] [0.84566 0.99364]   [0.13767 0.78618]   ] T
  [-0.03847 -0.81531] [ [-0.18704 -0.33282] [-0.95717 -0.6337]  [0.10976 -0.88374]  ] T
  [0.07904 -0.06245]  [ [0.95181 -0.84223]  [-0.75583 -0.34406] [0.16785 0.87519]   ] T
  [-0.33485 0.53875]  [ [-0.25173 0.51317]  [-0.62441 -0.90698] [-0.47925 0.74832]  ] T
  [-0.99103 0.43842]  [ [0.78128 -0.10985]  [-0.84714 -0.20558] [-0.08925 -0.78608] ] T
  [0.15087 -0.56212]  [ [-0.87374 -0.3787]  [0.86403 0.60374]   [0.01392 0.84362]   ] T
  [0.1114 0.66496]    [ [-0.92633 0.27408]  [0.92439 0.43692]   [0.8298 -0.29647]   ] T
  [0.87786 -0.8594]   [ [-0.42283 -0.97999] [0.58659 -0.327]    [-0.22656 0.80896]  ] T
  [0.43525 -0.8923]   [ [0.86119 0.78278]   [-0.01348 0.98093]  [-0.56244 -0.75129] ] T
  [-0.73365 0.28332]  [ [0.63263 0.17177]   [-0.38398 -0.43497] [-0.31123 0.73168]  ] T
  [-0.57694 -0.87713] [ [-0.93622 0.89397]  [0.93117 0.40775]   [0.2323 -0.30718]   ] T
  [0.91059 0.75966]   [ [0.60118 0.73186]   [0.32178 0.88296]   [-0.90087 -0.26367] ] T
  [0.3463 -0.89397]   [ [0.99108 0.13557]   [0.50122 -0.8724]   [0.43385 0.00167]   ] T
  [0.88121 0.36469]   [ [-0.29829 0.21429]  [0.31395 0.2734]    [0.43267 -0.78192]  ] T
]p;

$ cjam triangle.cjam
[1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0]

Bu adlandırılmış bir fonksiyon mu?
Martin Ender,

@ m.buettner: Sırala. Resmi wiki : Aşağıdaki diyor - Bir program bölümü ile sınırlanmış Blok {ve }tek bir birim olarak kabul. C / java'daki kod bloklarına benzer şekilde, bloklar birinci sınıf nesnelerdir ve değişkenlere atanabilir (bu nedenle işlevleri tanımlar).
Dennis,

1
@xnor 1m<@m*, 3 çift X ve i+1üçgenin bir sonraki (üçüncü ) tepe noktasını hazırlar . @-@@-Geçerli ( ith) tepe noktasını orijine kaydırır (ve değilse yansıtılır @-\@-, ancak önemi yoktur). @@*@@*>Çapraz ürünün z ekseni olan aka determinantı hesaplar ve 1negatifse döner . :+3%!hepsinin aynı olup olmadığını, yani, 3ünün de negatif mi yoksa negatif mi olduğunu döndürür, yani kenar durumlar dışında pozitif anlamına gelir. CJam'ı okumak golf oynamaktan daha zor.
jimmy23013

1
37 bayt: {[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T. Unicode güvenliği için 2m>veya kullanın Wm<.
jimmy23013

1
33 bayt:{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T
jimmy23013

5

C - 156 bayt

Girdiler, X'te 3 kayan, Y'de 3 kayan ve test noktası için ayrı x ve y dizileridir. Bonus: tüm kenar davalarını ele alır!

int f(float*X,float*Y,float x,float y){int i,j,c=0;for(i=0,j=2;i<3;j=i++)if(((Y[i]>y)!=(Y[j]>y))&&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[i]))c=!c;return c;}

PNPOLY'den uyarlanmıştır.


i;j;c;f(float*X,float*Y,float x,float y){for(c=i=0,j=2;i<3;)c^=(Y[i]>y)-(Y[j]>y)&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[j=i++]);return c;}137 - javascript'te test edildi
bebe,

@bebe - Bu bir sözdizimi hatasına neden olur.
Derek 功夫 會 功夫

O değil bir sözdizimi hatası neden olur.
bebe,

4

Pyth 1.0.5 , 57 54 51

DgYb=Z0J'bWbK;bDiHNR*-'H'K-@N1@K1~Z>iYJiJY=JK)R!%Z3

İki giriş alan g işlevini tanımlar: test noktası ve sonra üçgenin köşelerinin listesi. Çıktılar Trueve False. Not: Girdiyi, özellikle b, üçgenin köşelerinin listesini yok eder.

Burada dene . Son birkaç karakter, gvwvwsonraki iki satırda bir test durumu ile fonksiyonu çağırır.

Göre bu algoritma

Açıklama:

DgYb                  Define g(Y,b):
=Z0                     Z=0
J'b                     J=b[0]              (No = is needed because j is special).
Wb                      While len(b)>0:     (While b:)
K;b                       K=b.pop()
DiHN                      Define i(H,N):    
R*-'H'K-@N1@K1              Return half of the linked equation.
~ZiYJiJY                  Z+=i(Y,J)>i(J,Y)
=JK                       J=K
)                       Wend
R!%Z3                   return not Z%3==0   (True iff Z == 0 or 3)

CJam - Pyth savaşı devam ediyor!


Bu adlandırılmış bir işlev olmalıdır. Is wSTDIN girişini alarak?
xnor

@ xnor Oops, açıklamanın o kısmını kaçırdım. Düzenleyecektir.
isaacg

@xnor Yanıtı basan işlevlere izin verilir mi, yoksa yanıtı döndürmeleri gerekir mi? Şu anda, bu cevabı yazdırıyor, ancak bir karakter daha döndürmesini sağlayabilirim.
isaacg,

Cevabı geri ver.
xnor

Belki sayacı değiştirerek karakterleri kaydedebilir miyim ZBirlikte birikir o boş set ile Z|=sadece, o zaman uzunluğu görmek için testten geçirir 0'ın ya da 1görüldü? Python'da strateji daha uzun sürdü, ancak Pyth ilkellerini kullanarak buna değer.
xnor

4

J 64 45 (42 atamadan)

c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)

Atama, işlevin bir işlevi olması için gerekli değildir, bu yüzden sayıp saymayacağınızdan emin değilsiniz. Esnek girdiden faydalanma: (1 + köşe noktası) x (boşluğun boyutsallığı) dizisine sahip olmak istiyorum.

Burada bazı ekstra puanlar kazanmayı umuyoruz ...: Bu şey simpleksin herhangi bir boyutunda işe yarıyor, sadece bir düzlemdeki üçgenler için değil, 3 boyutlu uzayda 3 boyutlu bir piramit de. Ayrıca simpleksin köşeleri sayısı (n + 1) 'den küçük olduğunda da çalışır, daha sonra noktanın simpleks üzerine çıkıntısının içeride olup olmadığını hesaplar.

Barycentric koordinatlarına dönüşür , sonra noktanın dışarda olduğunu belirten negatif olanları kontrol eder. J'nin negatif için _ kullandığını unutmayın

NB. example in triangle
D =: 4 2 $ 1 1 0 0 3 0 0 2 NB. 4 rows , x first, then the vertices of the triangle

NB. subtract last vertex coordinates from the rest and drop reference node
n=: (}:-"1{:)

NB. preprocessed to barycentric coordinates
bar=: {. (, 1 - +/)@%. |:@}.

NB. all positive
ap =: *./@(>:&0)

insided =: ap@bar@n

inside D
1

Verilen örnekler üzerinde bir deneme:

   true =: 0 : 0
[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
)

   false =: 0 : 0
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]
)
   NB. replace - by _ to avoid problems
   NB. cut up per row, drop the [ ] and convert to numbers
   $dat_t =: ((4 2 $ ".)@}:@}.;._2) (true='-')} true ,: '_'
10 4 2
   $dat_f =: ((4 2 $ ".)@}:@}.;._2) (false='-')}false,: '_'
10 4 2
   NB. this results in arrays with shape 10 4 2

   NB. for each 4 x 2 array (rank 2), do c for all true instances
   c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)
   c"2 dat_t
1 1 1 1 1 1 1 1 1 1
   NB. the same for the false ones, demonstrating anonymous usage
   NB. still a function though (or verb in J parlance)
   *./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)"2 dat_f
0 0 0 0 0 0 0 0 0 0

Bir adlandırılmış işlev istedim, bu yüzden atama karakterleri sayılır. Poligonlara genelleme yapmak için bazı noktalar! ······
xnor

Aslında, çokgenlere değil, maksimum N+1köşeli N-boyutlu simplekslere genelleştiriyorum . Örneğin 3 boyutlu uzayda 4 köşe piramit veya 4 boyutlu uzayda 5 köşe tek taraflı. Köşelerin sayısı, N+1bu durumda, algoritma, simpleksin ortogonal çıkıntının simplex içerisine girip girmediğine bakıp bakmadığına bakar; Bu projeksiyon bitiş noktaları arasında olup olmadığını)
jpjacobs

4

HTML5 + JS, 13b + 146b / 141b / 114 karakter

HTML:

<canvas id=C>

JS (146b):

// @params: t1x, t1y, t2x, t2y, t3x, t3y, pointx, pointy
function T(a,b,c,d,e,f,g,h){with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

veya ES6 (141b):

T=(a,b,c,d,e,f,g,h)=>{with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

veya ES6 unicode obfuscated (114 karakter):

eval(unescape(escape('𥀽𚁡𛁢𛁣𛁤𛁥𛁦𛁧𛁨𚐽🡻𭱩𭁨𚁃𛡧𩑴𠱯𫡴𩑸𭀨𘠲𩀢𚐩𬡥𭁵𬡮𘁢𩑧𪑮𤁡𭁨𚀩𛁭𫱶𩑔𫰨𨐬𨠩𛁬𪑮𩑔𫰨𨰬𩀩𛁬𪑮𩑔𫰨𩐬𩠩𛁦𪑬𫀨𚐬𘐡𩱥𭁉𫑡𩱥𡁡𭁡𚁧𛁨𛀱𛀱𚐮𩁡𭁡𦰳𧑽').replace(/uD./g,'')))

demo: http://jsfiddle.net/xH8mV/

Unicode şaşırtmaca ile yapılan: http://xem.github.io/obfuscatweet/


Nokta tarafa yakın olduğunda doğru sonucu vermiş gibi görünmüyor: jsfiddle.net/L2B2A Tüm girişlerin (-1,1) arasında olduğu ve kodunuzun sadece 4 pikseli test ettiği için bunun olduğuna inanıyorum. köken.
Derek 功夫 會 功夫

bu doğru, örneklere uyması için içimdeki üçgenleri işlemek için tuvalimin kökenini ve ölçeğini değiştirmeliyim [-1,1]. Ama neden bu üçgenler zaten bu kadar küçük?
xem

sorun, xy'nin -1 ile 1 arasında olduğunu söylüyor. Gerçekten nedenini bilmiyorum, ancak her girişi 1e7 ile çarpabileceğinizi düşünüyorum (hassasiyeti korumak için) doğru sonucu alabilirsiniz: D
Derek 朕 會 功夫

Çok akıllıca bir grafik çözüm!
xnor

3

Python (65)

İnsanların gönderimi tamamlanmış gibi görünüyor, bu yüzden soruma kendi çözümümü göndereceğim.

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

Xtest noktalarını temsil eden karmaşık sayıdır ve Lher biri karmaşık bir sayı olan üç noktadan oluşan bir listedir.

İlk önce, kodun daha az golflü bir versiyonunu açıklayacağım;

def f(X,A,B,C):A-=X;B-=X;C-=X;return((A/B).imag>0)==((B/C).imag>0)==((C/A).imag>0)

Noktaları , Python'un yerleşik karmaşık aritmetiğinden yararlanarak, başlangıç noktasında A,B,C,Xolacak şekilde değiştiriyoruz X. Kökenin dışbükey gövdesinde olup olmadığını kontrol etmemiz gerekir A,B,C. Bu, AB, BC ve AC çizgi bölümlerinin her zaman aynı tarafında (sol veya sağ) bulunan orijine eşittir.

Bir parça ABA'dan B'ye almak için saat yönünün tersine 180 dereceden daha az hareket ederse solda orijinli, aksi takdirde sağda. Açılar göz önüne alınırsa a, bve c, bu noktalar, bu araçlar karşılık gelen b-a < 180 degrees(0 ila 360 derece açıların alınmıştır). Karmaşık sayılar olarak angle(B/A)=angle(B)/angle(A),. Ayrıca, angle(x) < 180 degreestam olarak kontrol ettiğimiz üst yarı düzlemdeki nokta için imag(x)>0.

Yani orijinin AB'nin solunda olup olmadığı olarak ifade edilir (A/B).imag>0. Bunların her bir döngüsel çift için eşit olup olmadığını kontrol etmek A,B,Cbize üçgenin ABCorijini içerip içermediğini gösterir.

Şimdi tamamen golf kurallarına dönelim.

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

Her döngüsel çifti üretiyoruz (A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X), etrafını saran negatif Python listesi endekslerinden yararlanarak ( L[-1]= L[2]). Bools'un hepsinin True( 1) ya da hepsi False( 0) olup olmadığını kontrol etmek için, onları ekliyoruz ve bölünebilirliği 3'e kadar, birçok çözümde olduğu gibi kontrol ediyoruz.


2

Fortran - 232 218 195 174

Kanlı korkunç. Veriler kendisine iletilme zorunluluğu nedeniyle işlev çok korkunçtur ve ön işleme alamıyoruz.

logical function L(x);real::x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4);L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s);endfunction

14 karakterin azalması, testlerimden fonksiyon ismini değiştirmeyi unuttuğum içindir. Diğer bir düşüş, örtük yazarak ve işlev adını değiştirmeyi unutmaktan kaynaklanır. Noktalarda tek bir dizi olarak okuma nedeniyle sonraki 20 karakter çıktı. Tam program

program inTriagle
   real, dimension(2) :: a,b,c,x
   do 
      print*,"Enter coordinates as x,a,b,c"
      read*,x,a,b,c
      if(all(x==0.0).and.all(a==0.0).and.all(b==0.0).and.all(c==0.0)) exit
      print*,"Is point in triangle: ",T(x,a,b,c)
   enddo
 contains!                       
   logical function L(x)
     real::x(8)
     p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3)
     s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4)
     L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s)
   endfunction
end program inTriagle

1
Fortran'ın örtük yazarak ve 8 sayının tümünü içeren tek bir giriş dizisini kullanarak bunu biraz daha kısaltabilirsiniz: logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);o=r*v-u*s;T=ALL([p*(s-v)+q*(u-r)+o,p*v-q*u,q*r-p*s]>=o);endListe işlemlerini kullanarak bunu daha da kısaltmaya çalıştım, ancak ne yazık ki bu pek işe yaramadı.
Ventero

1
Daha yaygın olan alt ifadeleri ortadan kaldırarak daha da kısa: Hatta logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);a=r*v-u*s;b=p*v-q*u;d=q*r-p*s;T=ALL([a-b-d,b,d]>=a);enddönüşümlerde hata yapmadım! Orijinal kodunuz tüm test durumlarını geçmiyor gibi gözükse de.
Ventero

@Ventero: Örtük yazmayı kötüye kullanmayı unuttuğuma inanamıyorum :(. Yardımınız için teşekkürler!
Kyle Kanos

@Ventero: Ayrıca, cevabım üçgenin yönüne bağlı görünüyor. İlk TrueOP örnek verir FalseI takas halinde Bve Cverirken 'in değeri Trueorijinal yönlendirme için.
Kyle Kanos,

Ah, gerçekten, soruna (önceki yorumumdaki gösterimi tekrar kullanarak) a < 0, test etmek zorunda olduğunuz koşulu etkili bir şekilde tersine çeviren neden olur. Maalesef, bu durum abs, her şeyi bir oraya sarmakla çözülemez , o zaman ima edilen koşul bve daynı işarete sahip olmak akaybolur. Bu, (tekrar, e=a-b-d;T=ALL([a*a-b*b,a*a-d*d,a*a-e*e,a*b,a*d,a*e]>=0)yorumumun ve son yorumumdaki önceden tanımlanmış değişkenlerin yeniden kullanılması) gibi bir şey kullanarak düzeltilebilir - muhtemelen daha fazla golf oynayabilir.
Ventero

2

MATLAB: 9!

Buraya yazacak fazla bir şeyim yok

inpolygon

Öyle çağrılabilir:

inpolygon(2/3, 2/3, [0 1 1], [0 0 1])

Çıktı adlı bir değişkene atanmış ans


Aslında bir işlev yazmak zorunda kalsaydım, bunun gibi bir şey olabilirdi, muhtemelen optimize edilebilirdi:

function y=f(a,b,c,d)
inpolygon(a,b,c,d)

2
bir işlev tutamacı kullanarak daha kısa olabilir:f=@(a,b,c,d)inpolygon(a,b,c,d)
jpjacobs

2

C # 218 (149?)

using P=System.Drawing.PointF;
bool F(P[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}P[]a=new P[3];Array.Copy(p,1,a,0,3);var g=new System.Drawing.Drawing2D.GraphicsPath();g.AddLines(a);return g.IsVisible(p[0]);}

Muhtemelen matematiksel bir yöntem kadar karakter verimli değildir, ancak kütüphanelerin eğlenceli bir kullanımıdır. Bu arada, aynı zamanda oldukça yavaş.

Ayrıca "Sayısal kararlılık veya kayan nokta hassasiyeti hakkında da endişelenmeyin." - maalesef, dahili olarak s GraphicsPathkullanır int, yani -1 <f <1 aralığındaki bir değer yalnızca üç olası değere sahip olabilir. Yüzdürmeler yalnızca 7 basamak hassasiyete sahip olduğundan, onları tam sayılara dönüştürmek için 1e7 ile çarparım. Hm, sanırım herhangi bir hassasiyetini kaybetmiyor . Aynı zamanda başka bir şekilde sömürülebilir: Muhtemelen hassasiyeti görmezden gelmekten ve "yanlış" cevabı vermekten faydalanabilirdim.

Eğer ben ithal kütüphanelerin karakter maliyetini görmezden izin var 149 (en azından, System.Linqve System.Drawingen WinForms projeler üzerinde oldukça standart, ama System.Drawing.Drawing2Dbir streç biraz olabilir):

bool G(PointF[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}var g=new GraphicsPath();g.AddLines(p.Skip(1).ToArray());return g.IsVisible(p[0]);}

Test programı (evet, çirkin):

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using P=System.Drawing.PointF;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Program prog = new Program();
        foreach (string test in
@"[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]".Split('\n'))
        {
            string t = test.Replace("[(", "").Replace(")]", "");
            string[] points = t.Split(new string[] { "), (" }, StringSplitOptions.None);

            string[] p = points[0].Split(',');
            P[] xabc = new P[4];

            for (int i = 0; i < 4; i++)
            {
                p = points[i].Split(',');
                xabc[i] = new F(float.Parse(p[0]), float.Parse(p[1]));
            }

            Console.WriteLine(test + "=>" + prog.F(xabc));
        }

        Console.ReadKey();
    }

    bool G(PointF[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }

    bool F(P[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new System.Drawing.Drawing2D.GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }
}

Sevimli, işi yapmak için çizim motorunu alıyorum.
xnor

2

Haskell - 233 127

Burada açıklandığı gibi çapraz ürünlerin kullanılması :

h(a,b)(p,q)(r,s)(t,u)=z a b p q r s==z a b r s t u&&z a b r s t u==z a b t u p q where z j k l m n o =(o-m)*(j-l)+(l-n)*(k-m)>0

Barycentric koordinatları ve bu Stack Exchange cevabında açıklanan formüller kullanılarak uygulanan önceki çözüm :

g(p,q)(r,s)(t,u)(v,w)=
 let (j,k)=(p+(-r),q+(-s))
     (l,m)=(t+(-r),u+(-s))
     (n,o)=(v+(-r),w+(-s))
     d=l*o-n*m
     a=(j*(m-o)+k*(n-l)+l*o-n*m)/d
     b=(j*o-k*n)/d
     c=(k*l-j*m)/d
 in (0<=a&&a<1)&&(0<=b&&b<1)&&(0<=c&&c<1)

Her iki fonksiyon gve hnoktası dahil ve üçgenin köşe koordinatlarının olarak geri kalanı için, test edilecek olan ilk olan dört çift, yazıldı.

Örnek girişi ile test etmek için:

let trueTestCases =
  [((-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)),
   ((-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)),
   ((0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)),
   ((-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)),
   ((0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)),
   ((-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)),
   ((-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)),
   ((-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)),
   ((0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)),
   ((-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832))]

let falseTestCases =
  [((-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)),
   ((0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)),
   ((0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)),
   ((0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)),
   ((0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)),
   ((-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)),
   ((-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)),
   ((0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)),
   ((0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)),
   ((0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192))]

type Point = (Double, Double)

test :: [(Point, Point, Point, Point)] -> [Bool]
test testCases =
  map (\((px,py),(ax,ay),(bx,by),(cx,cy)) -> h (px,py) (ax,ay) (bx,by) (cx,cy)) testCases

test trueTestCases --> [True,True,True,True,True,True,True,True,True,True]
test falseTestCases --> [False,False,False,False,False,False,False,False,False,False]

Ungolfed çözümler:

type Point = (Double, Double)

-- using cross products

triangulate' (a, b) (p, q) (r, s) (t, u) =
  (side a b p q r s == side a b r s t u) && (side a b r s t u == side a b t u p q)
  where side j k l m n o = (o - m) * (j - l) + (-n + l) * (k - m) >= 0

-- using barycentric coordinates

triangulate :: (Point, Point, Point, Point) -> Bool
triangulate ((px, py), (ax, ay), (bx, by), (cx, cy)) = 
  let (p'x, p'y) = (px + (-ax), py + (-ay))
      (b'x, b'y) = (bx + (-ax), by + (-ay))
      (c'x, c'y) = (cx + (-ax), cy + (-ay))
      d = b'x * c'y - c'x * b'y
      a = (p'x * (b'y - c'y) + p'y * (c'x - b'x) + b'x * c'y - c'x * b'y) / d
      b = (p'x * c'y - p'y * c'x) / d
      c = (p'y * b'x - p'x * b'y) / d
  in
      (0 <= a && a < 1) && (0 <= b && b < 1) && (0 <= c && c < 1)

2

JavaScript (ES6) 120

C=(p,q,i,j,k,l,m,n,
 z=j*(m-k)+i*(l-n)+k*n-l*m,
 s=(j*m-i*n+(n-j)*p+(i-m)*q)/z,
 t=(i*l-j*k+(j-l)*p+(k-i)*q)/z
)=>s>0&t>0&s+t<1

Doğrudan bu diğer soruya verdiğim yanıttan kopyalandı

FireFox / FireBug konsolunda test edin

1 sn çıkış

;[
C(-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633),
C(-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468),
C(0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497),
C(-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334),
C(0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028),
C(-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683),
C(-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618),
C(-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374),
C(0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519),
C(-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832)
]

0s çıktısı

;[
C(-0.99103, 0.43842,0.78128, -0.10985,-0.84714, -0.20558,-0.08925, -0.78608),
C(0.15087, -0.56212,-0.87374, -0.3787,0.86403, 0.60374,0.01392, 0.84362),
C(0.1114, 0.66496,-0.92633, 0.27408,0.92439, 0.43692,0.8298, -0.29647),
C(0.87786, -0.8594,-0.42283, -0.97999,0.58659, -0.327,-0.22656, 0.80896),
C(0.43525, -0.8923,0.86119, 0.78278,-0.01348, 0.98093,-0.56244, -0.75129),
C(-0.73365, 0.28332,0.63263, 0.17177,-0.38398, -0.43497,-0.31123, 0.73168),
C(-0.57694, -0.87713,-0.93622, 0.89397,0.93117, 0.40775,0.2323, -0.30718),
C(0.91059, 0.75966,0.60118, 0.73186,0.32178, 0.88296,-0.90087, -0.26367),
C(0.3463, -0.89397,0.99108, 0.13557,0.50122, -0.8724,0.43385, 0.00167),
C(0.88121, 0.36469,-0.29829, 0.21429,0.31395, 0.2734,0.43267, -0.78192)
]

2

SmileBASIC, 111 100 karakter

DEF T X,Y,A,B,C,D,E,F
Q=9e5GCLS
GTRI(A-X)*Q,Q*(B-Y),Q*(C-X),Q*(D-Y),Q*(E-X),Q*(F-Y)?!!GSPOIT(0,0)END

Bir üçgen çizer ve noktadaki pikselin rengini kontrol eder. Üçgen 99999x'e yükseltilir ve kaydırılır, böylece hassas nokta kaybını en aza indirmek için kontrol edilecek nokta çizilmeden önce (0,0) olacaktır.


2

Intel 8087 FPU düzeneği, 222 220 bayt

Hesaplamak için sadece 8087 FPU donanımını kullanır. İşte demonte (bu durumda da ungolfed) MACRO versiyonudur (220 hex bayt kodunu saklayacaktır):

; calculate the area of of a triangle ABC using determinate
; input: coordinates (float), Ax,Ay,Bx,By,Cx,Cy
; output: area in ST
TAREA   MACRO   A1,A2,B1,B2,C1,C2
    FLD  A1
    FLD  B2
    FLD  C2
    FSUB        ; ST = By - Cy
    FMUL        ; ST = Ax * ( By - Cy )
    FLD  B1 
    FLD  C2
    FLD  A2
    FSUB        ; ST = Cy - Ay
    FMUL        ; ST = Bx * ( Cy - Ay )
    FLD  C1
    FLD  A2
    FLD  B2
    FSUB        ; Ay - By
    FMUL        ; Cx * ( Ay - By )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay ) + Ax * ( By - Cy )
    FLD1        ; make a value of 2
    FADD ST,ST  ; ST = 2
    FDIV        ; divide by 2
    FABS        ; take abs value
        ENDM

; determine if point X is in triangle ABC
; input: points X, A, B, C
; output: ZF=1 if X in triangle, ZF=0 if X not in triangle
TXINABC     MACRO X1,X2,A1,A2,B1,B2,C1,C2

    TAREA  A1,A2,B1,B2,C1,C2    ; ST(3) = area of triangle ABC
    TAREA  X1,X2,B1,B2,C1,C2    ; ST(2) = area of triangle XBC
    TAREA  A1,A2,X1,X2,C1,C2    ; ST(1) = area of triangle AXC
    TAREA  A1,A2,B1,B2,X1,X2    ; ST(0) = area of triangle ABX

    FADD        ; add areas of triangles with point
    FADD        ; ST = ST + ST(1) + ST(2)
    FCOMPP      ; compare ST to ST(1) and pop results
    FWAIT       ; sync CPU/FPU
    FSTSW R     ; store result flags to R
    MOV  AX, R  ; move result to AX
    SAHF        ; store result into CPU flags for conditional check
        ENDM

açıklama

ABC üçgeninin alanını ve ardından X noktasıyla ve ABC üçgeninin diğer iki noktasıyla oluşturulan üçgeni hesaplamak için belirlemeyi kullanır. ABC üçgeninin alanı XBC + AXC + ABX üçgenlerinin alanlarının toplamına eşitse, nokta üçgen içindedir. Sonuç ZF olarak döndürülür.

Bunun nesi güzel

Tüm matematik ve kayan nokta işlemleri donanımda 80-bit genişletilmiş hassasiyetle yapılır. Son kayan nokta karşılaştırması da donanımda yapılır, bu yüzden çok doğru olacaktır.

Bu, aynı zamanda 8087’deki yığın kayıtlarının tümünü aynı anda kullanır.

Ne bu kadar temiz değil

Üçgenin noktaları hesaplama sırasında birkaç kez formüllere geri takılması gerektiğinden, bellekteki her bir değişkenin FPU'nun yığın yazmaçlarına bir defada doğru sırada yüklenmesini gerektirir. Bu bir MAKRO olarak bir fonksiyon gibi kolayca modellenebilse de, montaj sırasında her seferinde kodun genişletildiği ve yedek kodun yaratıldığı anlamına gelir. Aynı tekrarlanan kod bölümlerinden bazıları PROC'lere taşınarak 41 bayt kaydedildi. Ancak kodu daha az okunabilir kılar, bu nedenle yukarıdaki liste onsuzdur (bu nedenle "ungolfed" olarak etiketlenmiştir).

Testler

IBM DOS kullanarak çıktı gösteren bir test programı:

TTEST   MACRO T
        LOCAL IS_IN_TRI

    TXINABC T,T+4*1,T+4*2,T+4*3,T+4*4,T+4*5,T+4*6,T+4*7
    MOV  DX, OFFSET TEQ     ; load true string by default 
    JZ   IS_IN_TRI          ; if ZF=1, it is in triangle, skip to display
    MOV  DX, OFFSET FEQ     ; otherwise ZF=0 means not in triangle, so load false string
IS_IN_TRI:
    MOV  AH, 9              ; DOS write string function
    INT  21H 
        ENDM

START:
    FINIT                   ; reset 8087

    TTEST   T0              ; true tests
    TTEST   T1
    TTEST   T2
    TTEST   T3
    TTEST   T4
    TTEST   T5
    TTEST   T6
    TTEST   T7
    TTEST   T8
    TTEST   T9

    TTEST   F0              ; false tests
    TTEST   F1
    TTEST   F2
    TTEST   F3
    TTEST   F4
    TTEST   F5
    TTEST   F6  
    TTEST   F7
    TTEST   F8  
    TTEST   F9

    RET         ; return to DOS

T0  DD  -0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633
T1  DD  -0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468
T2  DD  0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497
T3  DD  -0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334
T4  DD  0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028
T5  DD  -0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683
T6  DD  -0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618
T7  DD  -0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374
T8  DD  0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519
T9  DD  -0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832

F0  DD  -0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608
F1  DD  0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362
F2  DD  0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647
F3  DD  0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896
F4  DD  0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129
F5  DD  -0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168
F6  DD  -0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718
F7  DD  0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367
F8  DD  0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167
F9  DD  0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192

TEQ DB 'In Triangle',0DH,0AH,'$'
FEQ DB 'Not In Triangle',0DH,0AH,'$'

Çıktı

In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle

1

C 414 (465 idi)

golfed

#define D double 
int F(D ax,D ay,D bx,D by,D cx,D cy,D px,D py){int y=0;double J,K;D m=(ax-bx<0.001)?(by-ay)/(ax-bx):1000;D b=m*ax+ay;J=m*cx-cy+b;K=m*px-py+b;if(J*K>=0)y=1;return y;}D T[8],k;int i,n;void G(){while(i<8){scanf("%lf",&k);T[i++]=k;}n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);printf(n==3?"True":"False");}

Açıklama için orijinal fonksiyon bildirimi eklendi

/**
* determine if points C & P are on same side of line AB
* return 1 if true, 0 otherwise
*/
int PointsSameSide(D ax,D ay,D bx,D by,D cx, D cy, D px, D py);

Adlandırılmış bir işlev olarak yeniden yazılmıştır: her satırdan bir tanesine stdin ile veya boşlukla ayrılmış bir satırdaki tümü.

#define D double
int F(D ax,D ay,D bx,D by,D cx, D cy, D px, D py)
{
int y=0;
double J,K;
D m = (ax-bx<0.001)?(by-ay)/(ax-bx):1000;
D b = m*ax+ay;
J=m*cx-cy+b;
K=m*px-py+b;
if(J*K>=0)y=1;
return y;
}
double T[8],k;
int i,n;
void G()
{
while(i<8){scanf("%lf",&k);T[i++]=k;}
n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);
n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);
n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);
printf(n==3?"True":"False");
}

3
Yeni hatlardan ve gereksiz alanlardan kurtularak bazı baytları kurtarabilirsiniz. Ayrıca, doubleolarak yeniden tanımladınız Dancak hala doublekodda kullanıyorsunuz.
gronostaj

1

Java, 149 karakter

g=Math.atan2(100*(d-y),(a-x));h=Math.atan2(100*(e-y),(b-x));i=Math.atan2(100*(f-y),(c-x));k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;

"Matematik" yazmam gerektiğini düşündüğüm için korkunç. her zaman. Bu gerçek program:

package mathPackage;
public class InTriangle {
public static void main(String[] args) {
    boolean k;
    double a=-1,b=0,c=1,d=0,e=1,f=0,x=0,y=0.4;
    double g,h,i;
    g=Math.atan2(100*(d-y),(a-x));
    h=Math.atan2(100*(e-y),(b-x));
    i=Math.atan2(100*(f-y),(c-x));
    k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;
    System.out.println(k);
    System.out.println(g);
    System.out.println(h);
    System.out.println(i);
    System.out.print(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g));
}
}

burada a, a'nın b, c'nin x'in c, c'nin x'in c olduğu, d'nin a'nın y'si olduğu, e'nin b'nin y olduğu, f'nin c'nin y'si olduğu ve x'in ve y'nin x olduğu ve noktanın y. Boolean k bunun doğru olup olmadığını belirler.


1
Ne 100*için?
xnor

1

JavaScript 125/198

Noktalar 8 argümanında sağlanmışsa:

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

Noktalar 2 boyutlu bir dizide sağlanıyorsa:

function c(s){return (z(s[1][0],s[1][1],s[2][0],s[2][1])+z(s[2][0],s[2][1],s[3][0],s[3][1])+z(s[3][0],s[3][1],s[1][0],s[1][1]))%3<1;function z(a,b,c,d){return (s[0][1]-b)*(c-a)-(s[0][0]-a)*(d-b)>0}}

Bu kod, bu süslü vektör matematiğinin hiçbirini kullanmaz. Bunun yerine, noktanın üçgenin içinde olup olmadığını belirlemek için yalnızca basit bir cebir numarası kullanır. Formül:

(y-b)(c-a) - (x-a)(d-b)

Bu, noktanın bir çizginin hangi tarafında olduğunu söyleyen, eğim tanımının yeniden düzenlenmesinden türetilmiştir:

            m = (y2-y1)/(x2-x1)
      (y2-y1) = m(x2-x1)
       (y-y1) = m(x-x1)     ,substituting point we are testing (x,y) to be the 2nd point
       (y-y1) = (x-x1)(y2-y1)/(x2-x1)  ,substitute back the original definition of m
(y-y1)(x2-x1) = (x-x1)(y2-y1)    <-- left side will be greater than the right side, if
                                     the point is on the left; otherwise, it's on the right
            0 = (y-b)(c-a)-(x-a)(d-b) ,where (a,b)=(x1,y1), (c,d)=(x2,y2)

Her üç tarafı da test edersek, her üçü de aynı işaretli bazı sayılar vermelidir, çünkü nokta üçgen içindeyken test edin. Nokta bir taraftaysa, testlerden birinin 0 döndürmesi gerekir.

jsFiddle test kodu: http://jsfiddle.net/DerekL/zEzZU/

var l = [[-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633],[-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468],[0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497],[-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334],[0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028],[-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683],[-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618],[-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374],[0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519],[-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832],
         [-0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608],[0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362],[0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647],[0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896],[0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129],[-0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168],[-0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718],[0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367],[0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167],[0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192]];

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

for(var i = 0; i < l.length; i++){
    console.log(d.apply(undefined,l[i]));    //10 true, 10 false
}

CoffeeScript'e dönüştürülürse, 97 karakter (boşluk veya sekme sayılmaz) sayılır:

d=(x,y,a,b,c,d,e,f)->
    z=(a,b,c,d)->
        (y-b)*(c-a)-(x-a)*(d-b)>0
    (z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1

ES6'ya dönüştürülürse 115 karakter :

d=(x,y,a,b,c,d,e,f)=>{z=(a,b,c,d)=>{return (y-b)*(c-a)-(x-a)*(d-b)>0};return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

Yani olan D (olmasa da bazı diğer yaklaşım koordine barycentric fantezi aldı): Ben kullanıyorum "fantezi vektör matematik". En çok oy alan cevap gibi, ES6'yı kullanarak ve benzeri işlevleri tanımlayarak birkaç bayttan tasarruf edebilirsiniz d=(x,y,...)=>{...}. Sizin durumunuzda, gerekmeyen CoffeeScript kullanarak daha da fazla tasarruf edebilirsiniz return: pastebin.com/RVFk1D5k ... ve her durumda <1yerine bir bayt kaydedebilirsiniz ==0.
Martin Ender

@ m.buettner: o Kullandığım denklemin vektörlerle ilgisi olmadığını düşündüm (basit cebirden türetilmiş) ancak görünüşe göre ikisi de aynı denklemi veriyor. Matematik harika.
Derek 功夫 會 功夫

1

R, 23

Esinlenerek MATLAB ,

SDMTools::pnt.in.poly()

gibi adlandırılan SDMTools::pnt.in.poly(point,triangle)burada pointbir uzunluk-2 vektörü ve triangleköşelerin bir 3x2 matristir. SDMTools, CRAN'da mevcuttur.


1

Mathematica, 38 karakter

RegionMember[Polygon[#[[1]]],#[[2]]] &

Örnek:

d = {{{0, 0}, {1, 0}, {.5, .7}}, {.5, .6}};

RegionMember[Polygon[#[[1]]], #[[2]]] & @ d

(* Doğru *)


Boşlukları karakter olarak saymak standarttır, ancak burada muhtemelen hiçbir şey kırmadan bunları kaldırabilirsiniz.
xnor

1
Ayrıca, önceden tanımlanmış değişkenleri kullanmak yerine girdi alıp çıktı üretmeniz gerekir. Nasıl yaptıklarını görmek için bazı Mathematica cevaplarını arayabilirsiniz.
xnor

0

C (gcc) , 108 bayt

i;f(a,b,c,d,e,f,g,h)float a,b,c,d,e,f,g,h;{i=(e-=a)*(h-=b)>(f-=b)*(g-=a);i=(c-=a)*f>(d-=b)*e==i&i==g*d>h*c;}

Çevrimiçi deneyin!

Üç çapraz ürün alır ve bileşenin 1işareti değişmezse geri döner .

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.