Dışbükey gövdede nokta (2D)


10

Arka fon

Dışbükey noktalarının sonlu sayıda olan en küçük konveks çokgen köşeler ya da iç kısmında, ya tüm noktaları ihtiva edecektir. Daha fazla bilgi için, PGM'de çok iyi tanımlayan bu soruya bakın .

Giriş

N+12-B koordinatları ( N >= 3) STDIN(diğer olağan golf girişlerine de izin verilir) aşağıdaki biçimde (ondalıkların sayısı değişebilir, ancak "makul" kaldığını ve her sayının bir kayan nokta olarak gösterilebileceğini varsayabilirsiniz):

0.00;0.00000
1;0.00
0.000;1.0000
-1.00;1.000000

Çıktı

Listedeki STDOUTilk nokta ( (0.00;0.00000)yukarıdaki örnekte) diğer N noktalarının dışbükey gövdesi içindeyse (veya eşdeğeri) yazdırılan doğruluk değeri, aksi takdirde bir falsy değeri.

Bu , bu nedenle bayttaki en kısa çözüm kazanır.

  • Sınır durumları : nokta dışbükey gövdenin sınırında (yani gövdenin dış sınırında bir tarafta veya bir tepe noktasında) ise, sıfır olasılık olduğu için herhangi bir değeri döndürebilirsiniz (ancak çökmeyin). olay (makul bir olasılık altında).

  • Yasak : yalnızca geometrik sorunları çözmek için var olan herhangi bir şey (dil, operatör, veri yapısı, yerleşik veya paket) (örn. Mathematica's ConvexHull ). Genel amaçlı matematiksel araçlara (vektörler, matrisler, karmaşık sayılar vb.) İzin verilir.

Testler


3
"Geçici veri yapısı" nedir?
DavidC

"temel fonksiyonlar / operatörler" çok belirsizdir.
xnor

@DavidCarraher: Çokgen, Üçgen veya Segment (sadece geometrik sorunları çözmek için var olan herhangi bir şey) gibi bir şey.
Alexandre Halm

2
@AlexandreHalm Düzenlemeniz çok yardımcı oldu. Bence "temel" doğru kelime değil. Bunun gibi genel amaçlı yerleşik ins ortadan düşündüm sortya round. Bence sadece geometri için özel olarak yapılmış hiçbir şeye izin verilmediğini söylemek daha açık. Bununla birlikte, iki listeyi vektör olarak ekleme işlevi hakkında ne söylenebilir? Veya karmaşık bir sayının argümanını (açısını) bulmak için bir işlev?
xnor

1
Bu yüzden Elmaslar insanlara yeni zorluklar göndermeden önce Sandbox'ı kullanmalarını istiyor .
kedi

Yanıtlar:


9

J 40 39 34 bayt

3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-

Anonim bir diyadik fonksiyon, bir nokta alarak p bağımsız değişkenler biri ve noktaların bir listesi olarak, P (bunun önemi hangisinin hangisi argüman yapar) diğer argüman olarak, ve dönen 0ya 1, eğer p dışında veya sırasıyla P dışbükey gövdesi içinde . Nokta p ve noktaları P , karmaşık sayılar olarak alınmıştır.

Misal

  is_inside =: 3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-

  0.5j0.5  is_inside  0j0 0j1 1j0 1j1
1
  1.5j0.5  is_inside  0j0 0j1 1j0 1j1
0

veya...

Python 2, fonksiyon, 121 103, tam program, 162

Python 3, 149 bayt

import sys,cmath as C
p,q,*P=[complex(*eval(l.replace(*";,")))for l in sys.stdin]
A=[C.phase((r-p)/(q-p+(q==p)))for r in P]
print(max(A)-min(A)>C.pi)

Orijinal yazı ile aynı formattaki girişi STDIN üzerinden alır ve p'nin P dışbükey gövdesinde olup olmadığını gösteren bir boole değeri yazdırır.


açıklama

Maksimum ve minimum (işaretli) arasındaki fark, herhangi bir nokta arasındaki açı olup programı testleri r içinde p , p , ve sabit bir rasgele nokta q içinde P (sadece ilk noktayı kullanmak P , ° az 180 daha). Diğer bir deyişle, bu tüm noktalar test eder , P , yaklaşık az 180 ° bir açıyla bulunan ° veya edilir p . p , ancak bu koşul yanlışsa P'nin dışbükey gövdesindedir .


Yukarıdaki durum söyleyerek eşdeğer olduğunu Not: birkaç bayt ücret karşılığında biz de benzer üzere açıkça hesapla açılar bize gerektirmez yöntemi kullanabilirsiniz p dışbükey gövde dışında P ancak ve varsa yalnızca bir satır l ile p tüm noktalar öyle ki, P aynı tarafta l . Böyle bir hat varsa, o zaman olay noktaların bir (veya daha fazla) olan bir çizgi de var P (biz döndürme l bu noktalar arasında bir temas edene kadar P ).

(Geçici) bu satırı bulmak için, izin vererek başlamak l geçen doğru p ve ilk nokta P . Sonra noktaların kalanını üzerinde yineleme P ; noktalardan biri l' in solundaysa (bir yönde bir yönelim olduğunu, sol veya sağın gerçekten önemli olmadığını düşünüyoruz), l yerine p ve o noktadan geçen çizgiyi koyarız ve devam ederiz. Önemli tüm iterated sonra P , (ve sadece) p sonra tüm noktalar, konveks gövdenin dış olduğu P (veya) sağında olmalıdır l . Biz de puan üzerinden ikinci bir geçiş kullanılarak kontrol P.

Python 2, 172 bayt

import sys
P=[eval(l.replace(*";,"))for l in sys.stdin]
x,y=P.pop(0)
C=lambda(a,b),(c,d):(a-x)*(d-y)-(b-y)*(c-x)>0
l=reduce(lambda*x:x[C(*x)],P)
print any(C(l,q)for q in P)


Alternatif olarak, izin tek geçişte aynısını yapmaya için-sol ve herhangi iki nokta arasında bir realtion olmak q ve r de, P , öyle ki, q, sol için r ise q solunda p ve r'den geçen hattın . İçin-sol-o ile ilgili bir emir ilişkidir Not P eğer tüm noktaları sadece P içinden geçen bir çizginin aynı tarafta p ise, olduğu, s konveks gövdenin dış olup , P . Prosedürü buluntular üzerinde en az noktası tarif Pwrt bu sıra, yani P "en soldaki" nokta . İki geçiş yapmak yerine, P'de aynı sırayla maksimum (yani "en sağdaki" noktayı) hem de minimum noktaları bulabilir ve minimumun tek geçişte olduğunu doğrulayabiliriz. maksimum, yani etkili bir şekilde sola doğru geçişlidir.

Bu iyi çalışacak p dışbükey gövde dışında P , bu durumda to-sola-aslında bir emir ilişkisi olmakla ne zaman bozabilir p (örneğin dışbükey gövde içinde olduğunu, ne olacak anlamaya çalışalım içinde noktaları bu algoritma bitince ne p saat yönünün tersine çalışan, düzenli beşgen noktalar vardır ve s . Biz bir nokta seçin: onun merkezidir) yerleştirmek için, biraz algoritma değiştirmek q içinde p ve kenarortay P içinden geçen bir çizgi boyunca p ve q (yani, biz bölümü P etrafında qwrt to-the-left-of.) Artık P'nin bir "sol kısmı" ve bir "sağ kısmı" var , her biri yarım düzlemde yer alıyor, böylece sola doğru her biri için bir sipariş ilişkisi; sol parçanın minimumunu ve sağ parçanın maksimumunu buluruz ve bunları yukarıda açıklandığı gibi karşılaştırırız. Tabii ki, biz fiziksel olarak kenarortay gerekmez P , biz sadece her noktayı sınıflandırabilirim P biz tek geçişte, minimum ve maksimum göründüğün gibi.

Python 2, 194 bayt

import sys
P=[eval(l.replace(*";,"))for l in sys.stdin]
x,y=P.pop(0)
C=lambda(a,b),(c,d):(a-x)*(d-y)-(b-y)*(c-x)>0
l=r=P[0]
for q in P:
 if C(P[0],q):l=q*C(l,q)or l
 elif C(q,r):r=q
print C(l,r)

(en azından Python biri, J yapabilirse hiçbir fikrim yok) STDIN giriş almak için herhangi bir şans? Çözümleri dengeli bir oyun alanı ile karşılaştırmanın daha kolay olacağını düşünüyorum. Girdinin zaten önceden biçimlendirilmiş karmaşık sayılar veya noktalar kümesi olduğunu varsayarsak, bir miktar gerdirilmiş IMO'dur.
Alexandre Halm

@AlexandreHalm Tam program eklendi.
Ell

Çözümlerinizi her dil için bir yanıta bölmelisiniz.
Mego

4

Oktav, 82 72 bayt

d=dlmread(0,";");i=2:rows(d);~isna(glpk(i,[d(i,:)';~~i],[d(1,:)';1]))&&1

Fikir, min {c'x: Ax = b, e'x = 1, x> = 0} doğrusal programının bir çözümü olup olmadığını kontrol etmek olup, burada e, hepsinin bir vektörüdür, A sütunları, nokta bulutu ve b test noktasıdır ve c isteğe bağlıdır. Başka bir deyişle, b'yi A sütunlarının dışbükey bir kombinasyonu olarak göstermeye çalışıyoruz.

Komut dosyasını çalıştırmak için şunu kullanın: octave -f script.m <input.dat


2

R, 207 bayt

d=read.csv(file("stdin"),F,";")
q=function(i,j,k)abs(det(as.matrix(cbind(d[c(i,j,k),],1))))
t=function(i,j,k)q(i,j,k)==q(1,i,j)+q(1,i,k)+q(1,j,k)
any(apply(combn(2:nrow(d),3),2,function(v)t(v[1],v[2],v[3])))

Komut dosyası girişlerini STDIN'den alır, örn Rscript script.R < inputFile.

Bu tüm üçgenler oluşturan Nson nokta (son satır, apply(combn(...ilk nokta kullanılarak üçgen olup olmadığını) ve çek tfonksiyonu.

tkarar vermek için alan yöntemini kullanan Uiçindedir ABC(yazma: (ABC)alan için ABC) Ubulunmaktadır ABCIFF (ABC) == (ABU) + (ACU) + (BCU). Ayrıca, alanlar determinant formülü kullanılarak hesaplanır ( Wolfram'dan güzel bir demo için buraya bakın ).

Bu çözümün sayısal hatalara diğerinden daha yatkın olduğundan şüpheleniyorum, ancak test vakalarımda çalışıyor.


0

R, 282 bayt

d=read.csv(file("stdin"),F,";")
p=function(a,b)a[1]*b[1]+a[2]*b[2]
t=function(a,b,c){A=d[a,];
U=d[1,]-A
B=d[b,]-A
C=d[c,]-A
f=p(C,C)
g=p(B,C)
h=p(U,C)
i=p(B,B)
j=p(U,B)
k=f*i-g*g
u=i*h-g*j
v=f*j-g*h
min(u*k,v*k,k-u-v)>0}
any(apply(combn(2:nrow(d),3),2,function(v)t(v[1],v[2],v[3])))

Komut dosyası girişlerini STDIN'den alır, örn Rscript script.R < inputFile.

Bu tüm üçgenler oluşturan Nson nokta (son satır, apply(combn(...ilk nokta kullanılarak üçgen olup olmadığını) ve çek tfonksiyonu.

tkarar vermek için barisentrik yöntemi kullanır Uiçinde ABC: (yazma XYiçin Xiçin Yvektör) yana (AB,AC)(A, B, C, hizalanır dejenere durumlar hariç) uçak için bir temel oluşturur, AUaşağıdaki gibi ifade edilebilir AU = u.AB + v.ACve Uüçgen IFF içinde u > 0 && v > 0 && u+v < 1. Daha ayrıntılı bir açıklama ve hoş bir etkileşimli grafik için buraya bakınız . Not: Birkaç karakter kaydetmek ve DIV0 hatalarından kaçınmak için uve sadece bir kısayol vve değiştirilmiş bir test ( min(u*k,v*k,k-u-v)>0) hesaplıyoruz .

Kullanılan tek matematiksel operatörleri +, -, *, min()>0.

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.