n個のノードを持つすべての二分木を列挙する


10

整数nを指定すると、n個の内部ノードを持つすべての可能な完全な二分木を列挙します。(完全な二分木は、すべての内部ノードにちょうど2つの子を持ちます)。ツリー構造は、1が内部ノードを表し、0が外部ノード(Null)を表すツリーの事前注文トラバーサルとして出力される必要があります。

最初の数nの例を次に示します。

0:
0

1:
100

2:
11000
10100

3:
1110000
1101000
1100100
1011000
1010100

これは、最も少ないキャラクターに賞金が支払われるコードゴルフです。ツリーは、1行に1つずつ標準出力に出力されます。プログラムは、コマンドラインまたは標準入力からnを読み取る必要があります。


私は迷路のような書記体系を作ろうとしたときにその問題について考えていました
Ming-Tang

ソリューションを宣言する前の標準的な期限は何ですか?
カイルバット

出力の順序付けが必要なこの問題のわずかなバリエーションとストリーミングに関心がありますか?
カイルバット、

@カイル・バット私の意見だけでも、私は興味がないと思います。私にとって、これらの問題の面白さの一部は代替アプローチを試すことであり、特定の順序を要求すると実行可能なアルゴリズムの数が制限される可能性があります。
migimaru 2011

回答:


3

Perl- 125 79文字

カウントには、「-ln」オプションの4文字が含まれます。stdinからnを取ります。

新しい建設的なアプローチ:

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

n-1の解から各ツリーの各リーフ( "0")に新しい内部ノード( "100")を代入して、nの解を形成します。

(この概念は、内部ノードを使用して逐次生成された文字列を検証するために[100-> 0]置換をリーフする他のソリューションに負っています。その概念に基づいて私の回答を書いた後、同じ0-誰かの中間編集で100を超える構成方法。)

以前の再帰的アプローチ:

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$_

再帰的なungolfed:

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)

コマンドラインから実行します。つまり、「php golf.php 1」は「100」を出力します。

編集:$ nから再帰するのではなく、0から文字列を構築する別の方法で4文字をカットします。短縮された三項演算子にPHP 5.3を使用します。それ以外の場合は、さらに2文字が必要です。

編集2:ループにいくつかの変更を加えてさらに4文字を保存しました。

編集3:私は別のアプローチを試みていましたが、最終的に古い方法の下にそれを得ました。

すべての木は、4 ^ n(またはn = 0の場合は0)と2 * 4 ^ nの間の整数のバイナリ表現と見なすことができます。この関数は、その範囲をループして、各数値のバイナリ文字列を取得し、「100」を「0」に置き換えることで繰り返し数値を減らします。最終的な文字列が「0」の場合、それは有効なツリーなので、出力します。

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文字

(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}

入力はstdinから読み取られます。

> echo 2 | ruby binary_trees.rb
10100
11000

編集1:変更されたIO(Lowjackerのコメントを参照)

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]

編集2:アルゴリズムを変更しました。

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

編集3:バージョンは3番目のアプローチを採用しています(migimaruのアイデアを使用)。

編集4:再び2文字。ミギマルさんありがとうございます。


stdinからの入力を受け入れるには、1文字短くなります。
ロージャッカー2011

また、配列の各要素を1行に出力するため*?\n、は必要ありませんputs
ロージャッカー2011

@Lowjackerありがとうございます。
ハワード

Rubyの学習を始めたばかりですが、{} whileの代わりに0whileを使用すると、キャラクターを保存できると思います。少なくともNetBeansでは機能します。
migimaru 2011

また、サブ!ここではgsub!の代わりに十分なので、これは保存できる別のキャラクターです。
migimaru 2011

1

Ruby 1.9 (80)(79)

DCharnessで使用される非再帰的で建設的なアプローチを使用します。

編集:1文字を保存しました。

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

0

Haskell 122文字

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のコードの重要な部分なので、他の言語で誰かが同様のソリューションを使用できる可能性があります。対角線が交差した場合、基本的に左下から右上に四角形でランダムに歩く。以下と同等:

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

私がこれを答えとして受け入れるつもりはないことに注意してください。
カイルバット

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.