Çokgendeki delik sayısı


11

Sorun : Bağlı bir çokgendeki delik sayısını sayın. Çokgenin bağlanabilirliği, giriş üçgenlemesindeki her üçgenin en az 1 tarafı başka bir üçgenle paylaşması ve böyle bir bağlı üçgen kümesi olması koşuluyla garanti edilir.

Girdi bir liste Larasında ndüzleminde nokta ve bir liste Tile ilgili girdileri ile 3-dizilerini 0...n-1. TÜçgendeki her bir öğe için , üçgenlemede bir üçgenin (t_1,t_2,t_3)üç köşesini (listeden L) temsil eder . Bunun 'çokgen üçgenleme' anlamında bir üçgenleme olduğuna dikkat edin , çünkü Tbu örtüşmede asla iki üçgen olmayacaktır . Ek bir koşul, girdiyi sterilize etmek zorunda kalmamanız Lve Therhangi bir tekrar içermemenizdir.

Örnek 1 : Eğer L = {{0,0},{1,0},{0,1},{1,2}}ve T = {{0,1,2},{1,2,3}}daha sonra belirtilen çokgen 0 bir delik sayısı vardır.

Şekil 1

Örnek 2 : Eğer L = {{0,0},{1,0},{2,0},{2,1},{2,2},{1,2},{0,2},{0,1},{.5,.5},{1.5,.5},{1.5,1.5},{.5,1.5}}ve T = {{5,6,11},{5,10,11},{4,5,10},{3,8,10},{2,3,9},{2,8,9},{1,2,8},{0,1,8},{0,8,11},{0,7,11},{6,7,11},{3,4,10}}çokgen girişi 2 olan bir çıkış ile sonuçlanmalıdır sonra.

şekil 2

Görev alan en kısa programı (veya fonksiyonu) yazmak için Lve Tgirdi olarak ve deliklerin sayısını verir. 'Kazanan' en az karakter sayısına sahip giriş olarak kabul edilecektir (geçici bitiş tarihi 1 Haziran).

Örnek giriş biçimlendirmesi (0 indekslemeye dikkat edin):

0,0
1,0
0,1
1,2
0,1,2
1,2,3    

1
"Çokgenin bağlantısı, giriş üçgenlemesindeki her üçgenin en az 1 tarafı başka bir üçgeyle paylaşması koşuluyla garanti edilir." -- Hayır. Bu yeterli bir durum değil. Örneğin T=1,2,3/1,2,4/5,6,7/5,6,8,. Her üçgen başka bir üçgenle bir kenarı paylaşır, ancak üçgenleme bağlantısı kesilir
John Dvorak

Girdinin geçerli bir kısmi üçgenleme (iki üçgen örtüşmediği ve iki kez üçgen bulunmadığı) ve üçgenleme bağlı olduğunu varsayabilir miyiz?
John Dvorak


Ayrıca, şeklin bağlantısının kesilmesi için sonlu bir nokta kümesinin çıkarılmasının mümkün olmadığı anlamında girdinin kenara bağlı olduğunu varsayabilir miyiz? (ör: T=1,2,3/1,4,5bağlı ancak kenar bağlantılı değil)
John Dvorak

2
Bitiş tarihleri ​​hakkındaki bu işletmenin neden son zamanlarda kırpılmaya başladığından emin değilim. Kabul edilen cevabı değiştirmenize izin verildiğinden bir bitiş tarihi belirlemenize gerek yok. İnsanları ilk cevabın rakipsiz olduğunu düşünmeye korkutmak için bir cevap seçmeden önce bir hafta bekleyeceğiniz zihinsel bir fikre sahip olmak mantıklıdır, ancak sitede aktif olduğunuz sürece seçilen cevabı değiştirebilirsiniz eğer birisi daha iyi bir mesaj gönderirse. İlgili meta tartışmalar arasında meta.codegolf.stackexchange.com/q/542/194 ve meta.codegolf.stackexchange.com/q/193/194
Peter Taylor

Yanıtlar:


5

GolfScript (23 karakter)

~.{2*2/~}%{$}%.&,@@+,-)

GolfScript dizi gösterimi ve tırnak (veya integral) koordinatlarını kullanarak giriş biçimini varsayar. Örneğin

$ golfscript codegolf11738.gs <<<END
[["0" "0"] ["1" "0"] ["2" "0"] ["2" "1"] ["2" "2"] ["1" "2"] ["0" "2"] ["0" "1"] [".5" ".5"] ["1.5" ".5"] ["1.5" "1.5"] [".5" "1.5"]] [[5 6 11] [5 10 11] [4 5 10] [3 8 10] [2 3 9] [2 8 9] [1 2 8] [0 1 8] [0 8 11] [0 7 11] [6 7 11] [3 4 10]]
END
2

( Çevrimiçi eşdeğeri )

veya

$ golfscript codegolf11738.gs <<<END
[[0 0] [1 0] [0 1] [1 2]] [[0 1 2] [1 2 3]]
END
0

( Çevrimiçi eşdeğeri )


5

Python, 71

Aşağıda istenen numarayı hesaplayan bir program ( fonksiyon değil ) yer almaktadır.

len(set().union(*(map(frozenset,zip(t,t[1:]+t))for t in T)))-len(L+T)+1

Örnek kullanım:

>>> L = ((0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,1),(.5,.5),(1.5,.5),(1.5,1.5),(.5,1.5))
>>> T = ((5,6,11),(5,10,11),(4,5,10),(3,8,10),(2,3,9),(2,8,9),(1,2,8),(0,1,8),(0,8,11),(0,7,11),(6,7,11),(3,4,10))
>>> len(set().union(*(map(frozenset,zip(t,t[1:]+t))for t in T)))-len(L+T)+1
2

Uyarıyı kullanmak için +1, sıralama yerine frozenset kullanarak, zip (daha önce hiç kullandığımı söyleyemem, kendimi tanımam gerekiyor.)
Kaya

3

APL, 36

{1+(⍴⊃∪/{{⍵[⍋⍵]}¨,/3 2⍴⍵,⍵}¨⍵)-⍴⍺,⍵}

İşlev Lsol argüman Tolarak ve sağ olarak alır.

Örneğin:

      L←(0 0)(1 0)(0 1)(1 2)
      T←(0 1 2)(1 2 3)
      L{1+(⍴⊃∪/{{⍵[⍋⍵]}¨,/3 2⍴⍵,⍵}¨⍵)-⍴⍺,⍵}T
0
      L←(0 0)(1 0)(2 0)(2 1)(2 2)(1 2)(0 2)(0 1)(.5 .5)(1.5 .5)(1.5 1.5)(.5 1.5)
      T←(5 6 11)(5 10 11)(4 5 10)(3 8 10)(2 3 9)(2 8 9)(1 2 8)(0 1 8)(0 8 11)(0 7 11)(6 7 11)(3 4 10)
      L{1+(⍴⊃∪/{{⍵[⍋⍵]}¨,/3 2⍴⍵,⍵}¨⍵)-⍴⍺,⍵}T
2

Açıklama, sağdan sola gidiyor:

  • ⍴⍺,⍵iki girdi vektörünü birleştirir ve uzunluklarını döndürür ( V + F)
  • Bir sonraki blokun içine adım atmak:
    • ¨⍵ soldaki işlevi sağ bağımsız değişkenin her öğesine uygular ve sonucu döndürür
    • ⍵,⍵ kendisiyle birleştirilmiş doğru argümanı döndürür
    • 3 2⍴vektör argümanını üç çift olarak şekillendirir. Bu durumda vektörün birinci ve ikinci, üçüncü ve birinci ve ikinci ve üçüncü öğelerini birleştirir.
    • ,/ vektör argümanına birlikte katılır
    • ⍵[⍋⍵] doğru argümanı sıralar
    • ∪/ kopyaları filtreler
    • ⍴⊃ yuvalanmış bir skaleri bir vektöre dönüştürür ve uzunluğunu döndürür.
    • Tüm işlev şekildeki kenar sayısını ( E) döndürür
  • 1 kendini açıklayıcı (umarım ...)

Tüm fonksiyon daha sonra geri döner 1+E-(V+F)veya 1-(F+V-E).


Hemen hemen GolfScript çözümümün yaptığı gibi. GolfScript'ten çok daha uzun olduğuna şaşırdım.
Peter Taylor

@PeterTaylor GolfScript çözümünüzün çok daha kısa olmasına şaşırdım! (Ama sonra tekrar, o ise GolfScript)
Volatilite

2

Mathematica, 93 (henüz golf oynamadı)

f[l_, t_] :=  Max@MorphologicalComponents[Erosion[Graphics[
                                                        GraphicsComplex[l, Polygon[t + 1]]], 1]] - 1

(Netlik için alanlar eklendi)

Test yapmak:

f[{{0, 0}, {1, 0}, {0, 1}, {1, 2}}, {{0, 1, 2}, {1, 2, 3}}]
(*
 -> 0
*)

{l, t} = {{{0, 0}, {1,   0}, {2,    0}, {2,     1}, {2,    2}, {1, 2}, {0, 2}, 
           {0, 1}, {.5, .5}, {1.5, .5}, {1.5, 1.5}, {.5, 1.5}}, 

           {{5, 6, 11}, {5, 10, 11}, {4, 5, 10}, {3, 8, 10}, {2, 3,  9}, 
            {2, 8,  9}, {1,  2,  8}, {0, 1,  8}, {0, 8, 11}, {0, 7, 11}, {6, 7, 11}, {3, 4, 10}}};
f[l, t]
 (*
  -> 2
 *)

Bu, belirli bir minimum boyuta sahip üçgenlere veya deliklere dayanmıyor mu (argüman Erosion)?
John Dvorak

@JanDvorak Belki yanılıyorum, ancak sonsuz hassasiyet aritmetiği kullanmadığınız sürece, herhangi bir çözümün belirli bir minimum boyuta ulaşana kadar çalışacağını düşünüyorum (üç noktanın hizalanıp hizalanmayacağına karar vermeniz gerekecek). Sadece bu tür bir çözümde problem açıkça belirtilir.
Dr. belisarius

topolojik yaklaşımı kullanırsanız, yapmanız gerekmez. Birbirine bağlı üç nokta varsa, orada sıfır alanlı bir üçgene ihtiyacınız vardır - aksi takdirde bir deliğiniz vardır.
John Dvorak

@belisarius. Wolfram Teknik Destek'ten sonuçlarımız arasındaki tutarsızlık hakkında aldığım cevap: "Merhaba - E-postanız için teşekkür ederim. Kodunuzun Mac ve Windows'ta farklı sonuçlar verdiğini onayladım. Bunun amaçlanan davranış olduğunu düşünmüyorum, bu yüzden Bu konuda geliştiricilerimize bir rapor verdim, bu konuda geliştiricilerimizden aldığım faydalı bilgileri aktaracağımdan emin olabilirsiniz. Başka sorularınız olursa lütfen bize bildirin ... Teknik Destek Wolfram Araştırma , Inc. "
DavidC

@DavidCarraher "Evet, başka sorularım var: Bana her hata için bir çek gönderir misin?"
Dr. belisarius

2

Ruby, 239 karakter (227 gövde)

def f t
e=t.flat_map{|x|x.permutation(2).to_a}.group_by{|x|x}.select{|_,x|x.one?}.keys
n=Hash[e]
(u,n=n,n.dup;e.map{|x|a,b=*x;n[a]=n[n[a]]=n[b]})until n==u
n.values.uniq.size+e.group_by(&:last).map{|_,x|x.size}.reduce(-1){|x,y|x+y/2-1}
end

sadece topolojiyi düşünüyorum. Köşe konumlarını hiçbir şekilde kullanmıyorum.

arayan (Mathematica veya JSON biçiminde T bekliyor):

input = gets.chomp
input.gsub! "{", "["
input.gsub! "}", "]"
f eval(input)

Ölçek:

f [[0,1,2],[1,2,3]]
#=> 0
f [[5, 6, 11], [5, 10, 11], [4, 5, 10], [3, 8, 10], [2, 3, 9], [2, 8, 9], [1, 2, 8], [0, 1, 8], [0, 8, 11], [0, 7, 11], [6, 7, 11], [3, 4, 10]]
#=> 2
f [[1,2,3],[3,4,5],[5,6,1],[2,3,4],[4,5,6],[6,1,2]]
#=> 1

Yay, euler karakteristik bir yaklaşım. Python'da böyle yaptım.
Kaya

2
@Kaya. (Bkz. Columbus Yumurtası en.wikipedia.org/wiki/Egg_of_Columbus ) Birisi sorunuza bir Eulerian cevabı verdikten sonra, başkalarının takip etme olasılığı büyük ölçüde artar. Yaklaşımın kendi başına keşfedilmesinin çok daha zor ve tatmin edici olduğunu garanti edebilirim, ancak daha sonra Euler'in polihedra ile yaptığı çalışma ile bağlantı kurar.
DavidC

2

Mathematica 76 73 72 67 62

Çok fazla denemeden sonra, köşe noktalarının kesin konumunun endişe duymadığını fark ettim, bu yüzden problemi grafiklerle temsil ettim. Gerekli değişmezler, üçgenlerin, kenarların ve köşelerin sayısı değişmez kaldı (hat geçişinden kaçınılması şartıyla).

Grafikte iki tür dahili "üçgen" vardı: bunlar muhtemelen bir yüz vardı, yani "dolu" bir üçgen ve olmayanlar. İç yüzlerin sayısının kenarlarla veya köşelerle herhangi bir ilişkisi yoktu. Bu, tamamen "doldurulmuş" grafiklerde deliklerin delinmesinin sadece yüz sayısını azalttığı anlamına geliyordu. Üçgenler arasındaki varyasyonlarla sistematik olarak oynadım, yüzleri, köşeleri ve kenarları takip ettim. Sonunda delik sayısının her zaman 1 - #faces - # vertices + #edges'e eşit olduğunu fark ettim. Bu 1 eksi Euler karakteristiği (sadece düzenli polihedra bağlamında bildiğim gibi) ortaya çıktı (kenarların uzunluğu açıkça önemsiz olmasına rağmen).

Aşağıdaki fonksiyon, köşeler ve üçgenler girildiğinde delik sayısını döndürür. Daha önceki gönderimin aksine, bir görüntünün taranmasına dayanmaz. Bunu 1 - Euler karakteristiği, yani 1 - (F + V-E) olarak Fdüşünebilirsiniz; burada = #faces, V= # vertices, E= # edge. İşlev 1 - (F + V -E), gerçek yüzler (üçgenler) ve köşeler göz önüne alındığında delik sayısını döndürür .

Kompleksin dışındaki herhangi bir üçgenin çıkarılmasının, bir veya 2 tarafı diğer üçgenlerle paylaşıp paylaşmamasına bakılmaksızın Euler karakteristiğini etkilemediği kolayca gösterilebilir.

Not: Küçük harf orijinal formülasyonun vyerine kullanılacaktır L; yani, köşeleri kendileri içerir (V değil, köşe sayısı)

f için kullanılır Torijinal formülasyondan ; yani, tepe indekslerinin sıralı üçlüsü olarak temsil edilen üçgenleri içerir.

kod

z=Length;1-z@#2-z@#+z[Union@@(Sort/@{#|#2,#2|#3,#3|#}&@@@#2)]&

(Değiştirme kuralını ortadan kaldırarak 5 karakter tıraş ettiği için Mr. Wizard'a teşekkürler.)


örnek 1

v = {{0, 0}, {1, 0}, {0, 1}, {1, 2}}; f = {{0, 1, 2}, {1, 2, 3}};

z=Length;1-z@#2-z@#+z[Union@@(Sort/@{#|#2,#2|#3,#3|#}&@@@#2)]&[v, f]

0

Sıfır delik.


ÖRNEK 2

v = {{0, 0}, {1, 0}, {2, 0}, {2, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1} , {.5, .5}, {1.5, .5}, {1.5, 1.5}, {.5, 1.5}}; f = {{5, 6, 11}, {5, 10, 11}, {4, 5, 10}, {3, 8, 10}, {2, 3, 9}, {2, 8, 9} , {1, 2, 8}, {0, 1, 8}, {0, 8, 11}, {0, 7, 11}, {6, 7, 11}, {3, 4, 10}};

z=Length;1-z@#2-z@#+z[Union@@(Sort/@{#|#2,#2|#3,#3|#}&@@@#2)]&[v, f]

2

Böylece, örnek 2'de 2 delik bulunmaktadır.


Temel olarak üçgenlemeyi rasterleştiriyor ve bu görüntü üzerine bir grafik kütüphanesi döküyor musunuz? Bir delik çok küçükse bu başarısız olmaz mı?
John Dvorak

1
ikinci örneğiniz burada 0 döndürür (bu yüzden kullanmadım MorphologicalEulerNumber[]). Mma 9.01, Win XP.
Dr. belisarius

9.0.1'i de kullanıyorum ama Mac'te. Mathematica'nın Windows'daki benimkinden farklı bir yanıt verdiğini mi söylüyorsunuz? Öyleyse, bu bir hata gibi geliyor (Windows XP sürümünde).
DavidC


@Jan Dvorak. MorphologicalEulerNumberbazen bir görüntü gerektirir; bir grafik nesnesini kabul etmeyi reddediyor. Bu durumlarda, deliğin boyutu ve çözünürlük kritiktir (bkz. Codegolf.stackexchange.com/questions/8706/… ). Ancak burada, doğrudan tüm köşeleri içeren Graphics nesnesiyle doğrudan çalışır. Resme bağlı olmayan bir yaklaşım kullanacağını düşündüm (veya umuyordum). Keşke sorunu nasıl çözmeye çalıştığını bilsem. Belki de fonksiyon için kaynak kodundaki bazı spelunking işleri netleştirecektir.
DavidC

1

Python, 107

Çiftleri doğrudan almanın from itertools import*ve yazmanın daha kısa olduğunu fark ettim.combinations() . Yine de, çözümümün köşeleri tutarlı bir şekilde listelenen giriş üçgen yüzlerine dayandığını fark ettim. Bu nedenle karakter sayısındaki kazanımlar o kadar büyük değil.

f=lambda l,t:1-len(l+t)+len(set([tuple(sorted(m))for n in[[i[:2],i[1:],[i[0],i[2]]]for i in t]for m in n]))

Python, 115

Euler karakteristik yaklaşımı, itertoolsun ayrıntı düzeyini önlemek imkansız görünüyor. Köşe çiftleri yapmak için daha doğrudan bir teknik kullanmanın daha ucuz olup olmayacağını merak ediyorum.

from itertools import*
f=lambda l,t:1-len(l+t)+len(set([m for n in[list(combinations(i,2)) for i in t]for m in n]))

Kullanım örneği:

> f([[0,0],[1,0],[0,1],[1,2]],[[0,1,2],[1,2,3]])
> 0
> f([[0,0],[1,0],[2,0],[2,1],[2,2],[1,2],[0,2],[0,1],[.5,.5],[1.5,.5],[1.5,1.5],[.5,1.5]],[[5,6,11],[5,10,11],[4,5,10],[3,8,10],[2,3,9],[2,8,9],[1,2,8],[0,1,8],[0,8,11],[0,7,11],[6,7,11],[3,4,10]])
> 2
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.