あなたの木を修正してください!


8

情報学では、多くの場合、さまざまな形式や表現で木を使用します。バイナリツリーをシリアル化する3つの主要な方法は、プレフィックス、インフィックス、ポストフィックス表記です。たとえば、次のバイナリツリー:

ツリー、インフィックス:rbxabde   (出典:オランダ情報学のオリンピック、決勝、2012/13)

プレフィックス表記としてabrxdberbxabdeインフィックスとして、ポストフィックスとしてとして表すことができますrxbbeda

この場合、中置記法で表現された完全なバイナリツリーに直面します。あなたの仕事は、このツリーをプレフィックス表記変換することです。あなたの入力 STDINには2になりますnは任意の整数のための改行文字で終了-1小文字のアルファベット文字、AZおよびこれ以上、nは、その結果1≤ N ≤16したがって、あなたが取得する文字の最大数は65535です。同じ方法でツリーをstdoutに出力しますが、その後、プレフィックス形式で出力します。

これはコードゴルフなので、バイト数で数えた最短のコードが勝ちます。投票はタイブレーカーとして機能し、それらがタイアップする場合は、提出日時。



@PeterTaylor言及していただきありがとうございます。式全体を評価する必要はなく、単純な2 <sup> _n _ </ sup> -1バイナリツリーを評価する必要がないため、この課題は実際には異なると思います。
tomsmeding 2014

OK、完全なバイナリツリーへの制限は物事をかなり単純化します
Peter Taylor

回答:


8

GolfScript、23文字

.,\{;).2base{)!}do}$/n-

このソリューションは、ハワードとは異なるアプローチを使用します。基本的に、ツリーのルートからその文字に到達するために必要なブランチのリストに従って入力文字をソートします。

入力の最後に改行が必要であることに注意してください(つまり、入力の長さは2の累乗でなければなりません)。n-コードの終わりには、出力の先頭に余分な改行を抑制するために必要とされます。そのような改行が受け入れられる場合は、21文字のスコアでこれらの文字を省略できます。

通常どおり、このコードをオンラインでテストできます。

説明:

  • .,\入力の長さを計算し、それをスタック上の入力文字列の下に移動します。以下のソートキーを構築するために使用されるループカウンターの開始値として使用されます。(コードは、これが2の累乗であることを前提としています。それ以外の場合、以下のビット操作は期待される結果を生成しません。ただし、十分に大きい2の累乗は機能します。)

  • { }$ ブロック内で計算された並べ替えキーに従って、入力文字列の文字を並べ替えます。

    • ;ブロックへの入力として与えられた文字を捨てるだけです。ここでは実際の文字値は関係ありません。文字列内の位置についてのみです。

    • ). スタックのループカウンター(入力文字列の長さに初期化された)をインクリメントし、そのコピーを作成します。

    • 2base このコピーをビットの配列に変換します(先行ゼロを省略しているため、単純にゼロからではなく、2の累乗からカウントを開始する必要があります)。

    • {)!}do切り落とされたビットがになるまで、配列の最下位ビットを繰り返し切り落とします1

    結果のソートキーは配列なので、は$辞書順に並べ替えます。したがって、たとえば、配列[1](ルートノードに対応)は(ルートノード[1 0]の左の子に対応)および[1 1](ルートノードの右の子)の前にソートされます。

  • 最後に、/出力文字列を分割するチャンクの長さとしてループカウンターを削除し(ありがとう、Peter!)、n-ソートされた入力文字列から改行を取り除きます。(GolfScriptインタープリターは、スタックの内容を出力した後、出力に別の改行を追加します。)


2
よくできました!さらに1つを保存でき\;ます。ループカウンターを削除する代わりに/、文字列をそれよりも大きいセクションに分割できます。(n-それによって、作成された配列からそれを引き出します)。
Peter Taylor

7

GolfScript、28文字

{.,1>{.,)2//([)\c]\~c+}*}:c~

オンラインでコードをテストできます

注釈付きコード:

# define an operator c acting on the top of stack which does the conversion
{
  # if the input string is more than a single character
  .,1>{
    # split string into two halves (rounded up)
    .,)2//   
    # take first part last character
    ([)
    # take first part rest and call c recursively
    \c]
    # get second part
    \~
    # call c recursively on second part
    c
    # join all three together 
    +
  }*
}:c
# call c
~       


3

APL(48)

(はい、APL文字セットは1バイトに収まります。)

{1=⍴⍵:⍵⋄(⊃a),⊃,/∇¨1↓a←1⌽⌽⍵⊂⍨(⍳⍴⍵)∊1,0 1+⌈.5×⍴⍵}⍞

説明:

  • {... }⍞:入力の読み取り、関数へのフィード
  • 1=⍴⍵:⍵:入力の長さが1の場合、これで完了です
  • : さもないと:
  • (⍳⍴⍵)∊1,0 1+⌈.5×⍴⍵:入力を分割する場所のビットフィールドを作成します(最初の文字、中間の文字、および中間の文字の後ろの文字)
  • ⍵⊂⍨:入力をこれらの場所で分割します
  • a←1⌽⌽:中央の文字が最初、左手が2番目、右手が3番目になるようにサブ配列を回転し、に格納しaます。
  • ⊃,/∇¨1↓a:の最後の2つの要素に対して関数を再度実行しa、結果を連結します
  • (⊃a),:それを最初の項目に連結します a

3

Python 3-76

def f(x):a=len(x)//2;return x and x[a]+f(x[:a])+f(x[a+1:])
print(f(input()))

1

C、108文字

私のコードは再帰関数を使用します。これは、常にバッファーの中央に文字を出力し、文字の前の部分と文字の後ろの部分を出力して自分自身を呼び出します。(分割統治)

char b[65536];d(s,e){int c=s+(e-s)/2;putchar(b[c]);if(c^s)d(s,c-1),d(c+1,e);}main(){gets(b);d(0,strlen(b));}

ゴルフなし:

char b[65536];
d(s,e){
    int c=s+(e-s)/2;
    putchar(b[c]);
    if(c^s)d(s,c-1),d(c+1,e);
}
main(){
    gets(b);
    d(0,strlen(b));
}

それは私が個人的にゴルフをしないソリューションで採用したアプローチでもあります。しかし、最短ではないようです...
tomsmeding
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.