Düğümlü tüm ikili ağaçları numaralandırma


10

N tamsayısı verildiğinde, n iç düğümü olan tüm olası tam ikili ağaçları numaralandırın. (Tam ikili ağaçların her iç düğümde tam olarak 2 çocuğu vardır). Ağaç yapısı, bir iç düğümü temsil eden ve 0 harici bir düğümü (Null) temsil eden, ağacın ön sıradan geçişi olarak çıktılanmalıdır.

İlk birkaç n için örnekler:

0:
0

1:
100

2:
11000
10100

3:
1110000
1101000
1100100
1011000
1010100

Bu, en az karaktere ödül kazanan bir kod golfü. Ağaçlar stdout'a her hat için bir tane çıkarılmalıdır. Program, komut satırından veya stdin'den n okumalıdır.


Labirent benzeri bir yazı sistemi yapmaya çalışırken bu sorunu düşünüyordum
Ming-Tang

Çözüm bildirmeden önce standart son tarih nedir?
Kyle Butt

Çıktının sipariş edilmesi gereken ve akışın yapıldığı bu sorunun küçük bir varyasyonunu yapmak ilginizi çeker mi?
Kyle Butt

@Kyle Butt Sadece benim fikrim, ama ilgileneceğimi sanmıyorum. Benim için, bu problemlerle eğlencenin bir kısmı alternatif yaklaşımları denemek ve belirli bir düzene ihtiyaç duyulması, muhtemelen uygulanabilir algoritma sayısını sınırlayacaktır.
migimaru

Yanıtlar:


3

Perl - 125 79 karakter

Sayım " -ln" seçenekleri için 4 karakter içerir . N'yi stdin'den alır.

Yeni yapıcı yaklaşım:

@a=0;map{%a=();map{$a{"$`100$'"}=1while/0/g;}@a;@a=keys%a}1..$_;print for@a

Her yaprak ("0") yerine n-1 çözeltisinden her ağaçta yeni bir iç düğüm ("100") değiştirerek n için çözeltiyi oluşturun.

(Bu kavramı, sırayla oluşturulan dizeleri doğrulamak için iç düğümü [100-> 0] yerine koymak için iç düğümü kullanan diğer çözümlerine borçluyum ve inanıyorum ki - bu kavramı temel alarak cevabımı yazdıktan sonra - bu aynı 0- > Birinin orta düzenlemesinde 100 inşaat yöntemi.)

Önceki özyinelemeli yaklaşım:

sub t{my$n=shift;if($n){--$n;for$R(0..$n){for$r(t($R)){for$l(t($n-$R)){push@_,"1$l$r"}}}}else{push@_,"0"}@_}print for t$_

Özyinelemeli olmayan:

sub tree {
  my ($n) = @_;
  my @result = ();
  if ( $n ) {
    for $right_count ( 0 .. $n-1 ) {
      for $right ( tree( $right_count ) ) {
        for $left ( tree( ($n-1) - $right_count ) ) {
          push @result, "1$left$right";
        }
      }
    }
  }
  else {
    push @result, "0";
  }
  return @result;
}
foreach $tree ( tree($_) ) {
  print $tree;
}

2

PHP (142) (138) (134) (113)

Komut satırından çalışır, yani "php golf.php 1" çıktıları "100".

DÜZENLEME: Alternatif bir yöntemle 4 karakteri kesin, $ n değerinden yineleme yapmak yerine dizeleri 0'dan oluşturun. Kısaltılmış üçlü operatör için PHP 5.3 kullanır; aksi takdirde 2 karakter daha gerekir.

DÜZENLEME 2: Döngülerde bazı değişikliklerle 4 karakter daha kaydetti.

DÜZENLEME 3: Farklı bir yaklaşım deniyordum ve sonunda eski yöntemin altına düştüm.

Tüm ağaçlar, 4 ^ n (veya n = 0 olduğunda 0 ile 2 * 4 ^ n) arasında tamsayıların ikili gösterimi olarak düşünülebilir. Bu işlev bu aralıkta dolaşır ve her sayının ikili dizesini alır, ardından "100" yerine "0" yazarak bunu sürekli olarak azaltır. Son dize "0" ise, geçerli bir ağaçtır, bu nedenle çıktı alın.

for($i=$p=pow(4,$argv[1])-1;$i<=2*$p;){$s=$d=decbin($i++);while($o!=$s=str_replace(100,0,$o=$s));echo$s?:"$d\n";}

2

Ruby, 99 94 92 89 87 karakter

(n=4**gets.to_i).times{|i|s=(n+i-1).to_s 2;t=s*1;0while s.sub!'100',?0;puts t if s==?0}

Giriş stdin'den okunur.

> echo 2 | ruby binary_trees.rb
10100
11000

Düzenleme 1: Değişen ES (Lowjacker'in yorumlarına bakın)

b=->n{n==0?[?0]:(k=[];n.times{|z|b[z].product(b[n-1-z]){|l|k<<=?1+l*''}};k)}
puts b[gets.to_i]

Edit 2: Değişen algoritma.

b=->n{n==0?[?0]:(k=[];b[n-1].map{|s|s.gsub(/0/){k<<=$`+'100'+$'}};k.uniq)}
puts b[gets.to_i]

Edit 3: Sürüm şimdi üçüncü yaklaşımı benimser (migimaru fikrini kullanarak).

Edit 4: Yine iki karakter. Migimaru'ya teşekkürler.


Stdin'den gelen girişi kabul etmek bir karakter daha kısa olacaktır.
Lowjacker

Ayrıca, dizinin her öğesini kendi satırına yazdırdığı için *?\n, buna ihtiyacınız yoktur puts.
Lowjacker

@Lowjacker Teşekkür ederim.
Howard

Ruby öğrenmeye yeni başladım, ancak bir karakteri {} while yerine 0} kullanarak kaydedebileceğinizi düşünüyorum. En azından NetBeans'te çalışıyor.
migimaru

Ayrıca, alt! burada gsub! yerine yeterlidir, bu yüzden kurtarabileceğiniz başka bir karakter.
migimaru

1

Yakut 1,9 (80) (79)

DCharness tarafından kullanılan özyinelemesiz, yapıcı yaklaşımın kullanılması.

EDIT: 1 karakter kaydedildi.

s=*?0;gets.to_i.times{s.map!{|x|x.gsub(?0).map{$`+'100'+$'}}.flatten!}
puts s&s

0

Haskell 122 karakter

main=do n<-readLn;mapM putStrLn$g n n
g 0 0=[['0']]
g u r|r<u||u<0=[]
g u r=do s<-[1,0];map((toEnum$s+48):)$g(u-s)(r-1+s)

IO, haskell'deki kodun önemsiz bir parçası olduğundan, belki de başka bir dilde benzer bir çözüm kullanabilir. Köşegen çapraz ise, soldan sağa doğru durmadan bir karede esasen rastgele yürür. Aşağıdakilere eşdeğer:

module BinTreeEnum where

import Data.List
import Data.Monoid

data TStruct = NonEmpty | Empty deriving (Enum, Show)
type TreeDef = [TStruct]

printTStruct :: TStruct -> Char
printTStruct NonEmpty = '1'
printTStruct Empty = '0'

printTreeDef :: TreeDef -> String
printTreeDef = map printTStruct

enumBinTrees :: Int -> [TreeDef]
enumBinTrees n = enumBinTrees' n n where
  enumBinTrees' ups rights | rights < ups = mempty
  enumBinTrees' 0   rights = return (replicate (rights+1) Empty)
  enumBinTrees' ups rights = do
    step <- enumFrom (toEnum 0)
    let suffixes =
          case step of
            NonEmpty -> enumBinTrees' (ups - 1) rights
            Empty -> enumBinTrees' ups (rights - 1)
    suffix <- suffixes
    return (step:suffix)

mainExample = do
  print $ map printTreeDef $ enumBinTrees 4

Bunu cevap olarak kabul etmek istemediğimi, sadece orada benimkini atacağımı düşündüm.
Kyle Butt

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.