Ağaçları say


11

Bir ağaç bir döngü ile bağlı, yönsüz grafiktir. Göreviniz, belirli sayıda köşe noktasıyla kaç farklı ağaç olduğunu saymaktır.

İzomorfik olmadıkları takdirde iki ağaç ayrı kabul edilir . Eğer ilgili köşeleri bir grafikte iki köşe arasında bir kenar olacak ve sadece diğer grafikte bu köşelere eşlenmiş köşeler varsa bir kenar olacak şekilde eşleştirilebiliyorsa, iki grafik izomorfiktir. Daha eksiksiz bir açıklama için yukarıdaki bağlantıya bakın.

1 ila 6 boyutlarındaki tüm farklı ağaçların nasıl göründüğünü görmek için buraya bir göz atın .

Çıktmaya çalıştığınız seri OEIS'te A000055 .

Kısıtlama : Girişinizde çalışması için çözümünüzün dakikalar veya daha kısa bir süre içinde olması gerekir 6. Bu, üstel zaman algoritmalarını ortadan kaldırmayı amaçlamaz, ancak tüm kenar kümelerinde kaba zorlama gibi iki kat daha fazla zaman algoritmalarını ortadan kaldırmayı amaçlamaktadır.

Girdi: Negatif olmayan bir tam sayı.

Giriş, STDIN, komut satırı parametresi, fonksiyon girişi vb. Dahil herhangi bir standart yolla olabilir.

Çıktı: Girdi kadar köşeye sahip farklı ağaçların sayısı.

Çıktı, STDOUT, işlev dönüşü vb. Dahil olmak üzere herhangi bir standart yolla olabilir.

Örnekler: 0, 1, 2, 3, 4, 5, 6, 7 dönmelidir 1, 1, 1, 1, 2, 3, 6, 11.

Puanlama: Kod golf, bayt. En kısa kod kazanabilir!

Standart boşluklar yasaktır.

Yanıtlar:


3

CJam (69 bayt)

]qi:X,{1e|,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/z

Çevrimiçi demo

açıklama

Temel fikir OEIS'te açıklanan üretme fonksiyonunu uygulamaktır. Giriş kötü bir özel durum, ama yaptığım son tweaks sonuçlandı - bu durumda 1 - böylece z (mutlak değer için) onu düzenler. Buradaki en tuhaf numara bu.0-1z

.*:+üç kez tekrarlanır ve ayıklanırsa bir bayt kaydedebilir gibi görünür {.*:+}:F~. Ancak, bu dış durum ile kesilir , çünkü dış döngüyü hiç yürütmez.0


Terimleri tekrar eden A000081 için yardımcı oluşturma işlevini kullanıyoruz

a[0] = 0
a[1] = 1
For n >= 1, a[n+1] = (sum_{k=1}^n a[n-k+1] * sum_{d|k} d * a[d]) / n

Eminim bazı diller ters Möbius dönüşümü için yerleşiktir , ama CJam değil; bulduğum en iyi yaklaşım d ile bir dizi eşleme oluşturmak ve daha sonra bir kullanarak noktaya çarpma yapmaktır . Burada , indeks 1'de bir başlangıç oluşturmanın uygun olduğunu unutmayın , çünkü ağırlıkları ayarlarken sıfıra bölmekten kaçınmak istiyoruz. Ayrıca, noktalama işlemine sağlanan iki dizi aynı uzunlukta değilse, daha uzun olan değerlere dokunulmadan bırakıldığını unutmayın: bu nedenle, ya ilk k terimleriniΣd|kdxbir[d]dk % d == 0 ? d : 0bir.*birk veya ağırlık dizisini n'ye yükseltir . İkincisi daha kısa görünüyor. Yani bu ters Möbius dönüşümübirnN\f{1$%!*}W$.*:+

Biz Möbiüs dönüşümü, ters sonucu çağrı durumunda M, şu an sahip

bir[n+1]=1nΣk=1nbir[n-k+1]xM[k]

Pay, açık bir şekilde bir evrişimden geçen bir terimdir, bu nedenle veya M'nin bir kopyasını tersine çevirip daha sonra noktasal bir çarpma ve toplama yaparak bunu halledebiliriz . Yine, bizim endeks değişir 1'e kadar n ve ek olarak biz hangi toplamı endekslerini yukarı eşleştirmek istediğiniz n + 1 endeksin tekrar uygundur, böylece a Şimdi sorumluydu ettik 1 yerine 0 danbirM1nn+1bir

 qi:X,{   ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/

Yardımcı üretme fonksiyonunun noktası A000055'in formül bölümü tarafından verilir:

G.f.: A(x) = 1 + T(x) - T^2(x)/2 + T(x^2)/2,
where T(x) = x + x^2 + 2*x^3 + ... is the g.f. for A000081.

Açısından biz aramak çıkışı, bu araç olduğu [ X = 0 ] + a [ x ] + 1bir

[x=0]+bir[x]+12(bir[x/2]-Σben=0nbir[ben]xbir[n-ben])

bir[x/2]x1,*X=

0\+bir[0]=0X=0W\+-2bir[x]+Σben=0nbir[ben]xbir[n-ben]2bir[x]

Bu yüzden açıkladık

 qi:X,{   ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/

1]N-=1

1]qi:X,1>{ ... }/

X=0bir[-1 1]0[x=0]X!+1e|

bir1N-=0

]qi:X,{ ... /+}/

açıkça sıfıra bölme verir. Ama denersek

]qi:X,{1e| ... /+}/

sonra çalışır. Biz olsun

             e# Stack: [] 0
1e|          e# Stack: [] 1
,:):N        e# Stack: [] [1]
{            e# We only execute this loop once
  N\f{1$%!*} e#   1 divides 1, so stack: [] [1]
  W$.*       e#   Remember: if the two arrays supplied to the pointwise operation
             e#   are not the same length then the values from the longer one are
             e#   left untouched. Stack: [] [1]
  :+         e#   Fold over a singleton. Stack: [] 1
}%           e# And that was a map, so stack: [] [1]
1$W%.*:+     e# Another [1] [] .*:+, giving the same result: 1
N,/          e# 1 / 1 = 1
+            e# And we append 1 to a giving [1]

tam da ihtiyacımız olan değeri üretir.

X=0-1[-1](-1-12(-1x-1))=-101-11z


1

Pyth, 35 bayt

l{m`SmSSMcXdUQk2.pQusm+L,dhHGhHtQ]Y

Gösteri.

Bu program iki bölüme ayrılabilir: Birincisi, olası tüm ağaçları üretiyoruz, sonra kopyaları kaldırıyoruz.

Bu kod, ağaçlar oluşturur: usm+L,dhHGhHtQ]Y. Ağaçlar, şunun gibi birleştirilmiş bir kenar listesi olarak temsil edilir:

[0, 1, 0, 2, 2, 3, 1, 4]

Her sayı bir tepe noktasını temsil eder ve her iki sayı bir kenardır. Zaten mevcut olan her olası tepe ile yeni oluşturulan bir tepe noktasına tekrar tekrar bir kenar ekleyerek ve bunu önceki adımdaki olası her ağaca ekleyerek oluşturulur. Bu, tüm olası ağaçları oluşturur, çünkü tüm ağaçlar, mevcut ağaca bir tepe noktası ve bir kenar ekleyerek tekrar üretilebilir. Ancak, izomorfik ağaçlar oluşturulacaktır.

Sonra, her ağaç için olası her yeniden etiketleme işlemini gerçekleştiriyoruz. Bu, köşelerin ( m ... .pQ) tüm olası permütasyonları eşlenerek ve daha sonra ağacın standart siparişten bu sıralamaya dönüştürülmesi ile yapılır XdUQk. dağaç, kpermütasyon.

Ardından, kenarları ayrı listelere c ... 2ayırırız, her kenardaki köşeleri ile sıralar SM, ağacın içindeki kenarları sıralar S, her ağacın kanonik bir temsilini veririz. Bu iki adım koddur mSSMcXdUQk2.pQ.

Şimdi, her bir ağacın olası her yeniden etiketlemesinden oluşan listelerimiz var. Bu listeleri sıralıyoruz S. Herhangi iki izomorfik ağaç, ağaç grubuna yeniden etiketlenebilmelidir. Bu gerçeği kullanarak, her listeyi bir dizeye dönüştürdük `, sonra bu listelerin kümesini oluşturduk {ve uzunluğunu çıktı olarak verdik l.

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.