線形化されたツリーですか?(幅優先版)


11

バックグラウンド

ラベルのないツリーは次のようになります。

   o
 / | \
o  o  o
|    / \
o   o   o

このツリーを線形化するには、まず各ノードoにその子ノードの数でラベルを付けます。

   3
 / | \
1  0  2
|    / \
0   0   0

そして、一行ごとに、左から右へという意味で、数字をリストに一気に書きます。

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

これは、上記のツリーの一意かつ明確な表現です。つまり、2つの異なる純粋なツリーが同じ線形化を持たず、リストから元のツリーを再構築できることを意味します。

各ツリーは特定の整数リストに対応しますが、各整数リストは有効な線形化されたツリーを[2, 0, 0, 0]表すわけではありません。たとえば、有効なツリーを表しません。

[2,0,0,0] -> 2 [0,0,0] -> 2 [0,0] -> 2 [0]
            / \          / \        / \
                        0          0   0

ただし0、リストにはまだ左があり、配置する場所はありません。同様に[2, 0]、非線形化ツリーには空の子スポットがあるため、有効なツリー線形化でもありません。

  2
 / \
0

仕事

整数リストが与えられたら、それが可能な限り少ないバイトを使用してツリーの有効な線形化であるかどうかを決定します。完全なプログラムまたは関数を作成できます。

入力: 負でない整数の空でないリスト。

出力: リストがツリーの線形化の場合は真理値、それ以外の場合は偽値。

テストケース

真実の
[0]
[2, 0, 0]
[1, 1, 1, 1, 1, 0]
[3, 1, 0, 2, 0, 0, 0]
[2, 0, 2, 2, 0, 0, 2, 0, 0]
[3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0]
[1, 5, 3, 0, 2, 1, 4, 0, 1, 0, 0, 2, 1, 0, 0, 1, 1, 0, 0, 0, 0, 2, 1, 0, 0, 1, 0]
偽物
[0, 1]
[2, 0]
[2, 0, 0, 0]
[1, 0, 1]
[3, 2, 1, 0]
[2, 0, 0, 2, 0, 0]
[4, 1, 0, 3, 0, 0, 0, 0]
[4, 2, 0, 3, 1, 0, 0, 0, 0, 0]

回答:


4

Haskell、44バイト

f[n:k]=iterate f[k]!!n
f _=[]
g x=f[x]==[[]]

gリストを取り、ブール値を返す関数を定義します。 すべてのテストケースに合格することを確認してください

説明

これは、深さ優先および幅優先の線形化が同じ配列を生成するという事実に依存しています。詳細については、Martinの回答を参照してください。基本的に、どちらも配列に同じ算術条件を与えます。

この関数にfは、シングルトンリストにラップされた入力リストが与えられます。nリストから1つの番号をポップnし、残りのリストで自分自身を呼び出して、ポップされたノードの子を処理します(深さ優先)。空のリストをポップ[]すると、エラー状態として使用するが発生します。この関数gは、最終結果が[[]]であるかどうかをチェックします。これは、未処理のノードのない一意のエラーのない状態です。Haskellが弱く入力された場合0、エラー状態としてまたはを使用でき、入力を別のリストにラップする必要はありません。


3

Mathematica、38バイト

Last@#<0<=Min@Most@#&@Accumulate[#-1]&

基本的な考え方は、入力するノードの数を追跡することです。リスト内の各要素は1つのノードを使用し、子を持つ数だけ追加します。したがって、各要素iは合計カウントをで変更しi-1ます。このカウントは1つずれて10ます。なぜなら、ではなく(ルート)から開始する必要があるからです。

ツリーを有効にするには、0a)現在のノードを配置する場所がないため、リスト全体を下に移動することはできません。b)最後に終了する必要があり-1ます。

残りのノードの現在の合計を取得しますAccumulate[#-1](入力リストから1を引いたプレフィックスの合計を計算します)。そして、最後の要素と最後の要素のみが次のものにあることを確認-1します。

Last@#<0<=Min@Most@#

最後の要素が負であることを確認するだけで十分であることに注意してください1。これ以上減少することはないため、最後の値が-2それ以下の場合、他の最小値が負でないことは不可能です。


2

網膜、29バイト

\d+
$*
^(?<-1>(1)*,)*$(?(1)!)

オンラインでお試しください!(最初の行は、改行で区切られたテストスイートを有効にします。)

説明

基本的な考え方は、私のMathematicaの答えと同じです。残りのノードの実行中の合計を追跡し、ゼロ未満にならないように、ゼロで終了するようにします。ただし、これを正規表現で実装する方法は非常に異なります。

\d+
$*

これは単純に入力を単項に変換し、各整数nn1に変換します。

^(?<-1>(1)*,)*$(?(1)!)

これが本当の魔法が起こる場所です。有効なツリーのみに一致するかなり短い正規表現ですが、仕組みは非常に微妙です。

バランシンググループを使用して、ノードの数を追跡します。これは、正規表現内のスタックを操作する方法です。

まず最初に、もちろん、そのようなスタックは負の深さになることはありません-1。そのため、Mathematicaソリューションで行うように、最後にを表すことはできません。しかし、我々は、入力の最後の要素があることに注意することができている(そうでない場合、我々はで終わることができませんでした有効なスタック上ゼロです-1)。ゼロで終わるノードとゼロで終わるノードの両方をチェックするために実際にバイトを節約することがわかります。

正規表現の内訳は次のとおりです。

^        e# Anchor the match to the beginning of the string.
(?<-1>   e# Each repetition of this group will match one number. 
         e# We can ignore the <-1> for now.
  (1)*   e#   Match each unary digit of the current number, pushing
         e#   a capture onto stack 1. This increments our total of
         e#   remaining nodes by 1 for each child.
  ,      e#   Match a comma. Note that this requires that there is at
         e#   least one more number in the list.
)*       e# At the end of the repetition the <-1> pops one capture from
         e# the stack. This is the node that the current number itself
         e# takes up.
$        e# Match the end of the string. This requires the input to end
         e# in a zero, because the last thing we matched was a comma.
(?(1)!)  e# Make sure that stack 1 is empty, so that we don't have any
         e# unused nodes.

1

CJam(20バイト)

{X0@{+\(_0>{\}*}/|!}

オンラインテストスイート。これは、スタック上の配列を受け取り、スタック上に0または1を残す匿名ブロックです。

解剖

擬似コードでは、これは次のとおりです。

p = 1
q = 0
foreach (i in input):
  q += i
  if (--p <= 0):      # in practice, if (--p == 0):
      p, q = q, p
return (p | q) == 0   # i.e. p == 0 && q == 0

qツリーの現在のレベルでノードのラベルの合計を蓄積します。p現在のレベルに残っているノードをカウントダウンします。


{X0@{+\(_{\}&}/|!}おもう?
マーティンエンダー

また、それを回避するために完全なプログラムを使用してバイトを保存できるはず@です。
マーティンエンダー

1

ラビリンス、17バイト

(
+?
;-)
,_"
@@,!

オンラインでお試しください!

真実の出力は-1あり、偽の出力は空です。Labyrinthの枝は主に3成分であるため、Labyrinthで真実と虚偽を定義するのは少し難しいです。ただし、2つのブランチを確実に使用して条件を作成する唯一の方法は、次の方法のみです。

>"F
 T

この場合、私は(動きの方向が影響を受けないので)真っ直ぐに虚偽に移動し、真実に変わることを検討したいと思います。これらはそれぞれゼロと非ゼロに対応します。空の出力を使用してゼロを表すのは、出力を別のLabyrinthプログラムにパイプで戻す?場合、入力が空の場合に入力演算子が実際にゼロをプッシュするため、空の文字列が有効であると見なされるためですゼロの表現。

説明

アルゴリズムは私のMathematicaとRetinaの回答と同じですが、迷路の制御フローにより、今回は少し異なります:

  • ここでは、トータルカウンターを1つずつオフにしては動作しません。代わりに、a)負のカウンターで作業し、b)-11最初に初期化して、リスト全体でカウンターを負にして、最後の入力でゼロをヒットするようにします。これにより、実際の制御フローが簡素化されます。
  • 完全なリストを作成して、間違った値が含まれているかどうかを確認する代わりに、次の3つの終了条件が考えられます。

    1. 合計カウントがゼロに達する前にEOFをヒットしました。その場合、未使用のノードが残っており、何も出力しません。
    2. 私たちは、ゼロに達する、私たちはEOFにいます。この場合、有効なツリーがあります。
    3. ゼロに達し、まだEOFではありません。この場合、すべての要素をカバーする前にノードを使い果たし、何も出力しません。

実際のコードについては、左上隅から始めます。(スタックの上に暗黙ゼロ点灯-1積算合計となり、。次に、プログラムの非常にタイトなメインループに入ります+?-)"_,;+

+   Add the top two values. This does nothing on the first iteration,
    but gets rid of a helper-zero on subsequent iterations.
?   Read and push integer.
-   Subtract it from running total.
)   Increment.
"   No-op. There is a branch at this point. If the running total is zero,
    we move straight ahead onto the , (see below). Otherwise, the loop continues.
_   Push a zero. This is necessary to prevent the IP from turning south.
,   Read a character. This will either be the next separator (some positive
    number) or EOF (-1). If it's EOF, the IP turns south and the program
    terminates. Otherwise, the loop continues.
;   Discard the separator.

そのため、ある時点で合計をゼロに減らした場合のみが残ります。IPは右下に移動し、,別の文字を読み取ってEOFに到達したかどうかを確認します。そうでない場合、値は正になり、IPはに向かって西向きに@なり、プログラムは終了します。EOFに到達した場合、IPは東を向き、-1with を出力し!ます。IPは@、プログラムを終了するために、少し奇妙なパスを介して左下に向かってワームします。


0

Python、82バイト

lambda l:len(l)==sum(l)+1 and not any(list(l[x]>=len(l)-x for x in range(len(l))))

さらにテストケースが必要です。


あなたはとキャストする必要はありませんlist、これは、少なくともPythonの2である場合、第二の条件を再配置し、反転させることによって、あなたは70バイトにそれを得ることができます:lambda l:all(l[x]<len(l)-x for x in range(len(l)))and len(l)==sum(l)+1
カーデ

^これに関連して、あなたがのボディに変更することができallなければx<len(l)-y for y,x in enumerate(l)68にそれを得るために、別の2つのバイトを保存するために
カーデ

私はこれが正確な解決策だとは思わないので、今これ以上ゴルフをしていません。ヒントをありがとう。
スパー

0

Pyth、13バイト

qxsM._tMQ_1tl

入力表現のすべてのポイントでツリーの現在の充足度を計算することから始めます。アイデアのその部分は、主にマーティン・エンダーから借用されているので、彼に感謝します。sM._tMQ

このリストを作成したら、-1x..._1)を含む最初のインデックスが入力の長さから1を引いたもの(q...tl(Q))かどうかを確認します。

それが機能するとは思わない?自分で試してみてください!

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