これは本当のツリーですか?


20

入力として文字列を受け取り、入力がASCIIツリーの場合は出力または返すプログラムまたは関数を作成する必要があります。

  _
\/  /
 \_/
  |
  |

ASCIIツリーは文字/ \ | _ spacesとで構成されますnewlines

非空白文字は、セルの2つのエッジポイントをラインセグメントで接続します。

  • / 左下隅と右上隅を接続します
  • \ 右下隅と左上隅を接続します
  • | 下端と上端の中間点を接続します
  • _ 左下隅と右下隅、および下端の中間点を接続します

(なお、この手段|のみで接続することができます|_ではなくて/\。)

次の規則が適用される場合、ASCIIピクチャはツリーと呼ばれます。

  • 正確に1つの文字の正確に1つのポイント(ルート)が最後の行の下端に接触します。
  • 次の方法で、任意の線セグメントの任意のポイントに到達できます。

    • ルートから始まる
    • 線分のみを使用する
    • 下方向には決して行かない(横方向にも下がらない)

入力

  • 文字列の文字から成る/ \ | _ spacenewline少なくとも1つの非空白文字を含みます。
  • 次の2つの入力形式から選択できます。

    • ツリーの周りに不要な空白はありません(例で見られます)。
    • すべての行を同じ長さにするための行の右側のスペースを除いて、ツリーの周りに不要な空白はありません(例にあります)。
  • 末尾の改行はオプションです。

出力

  • 入力がasciiツリーの場合、一貫した真理値。
  • 入力がasciiツリーでない場合、一貫した偽の値。

有効なツリー:

|
  _
\/  /
 \_/
  |
  |
/ /    \/
\ \____/
 \/
 /
/
 \___/
 /   \
 \___/
   |
   |
   __/
 _/
/
____
  \  ___
 \ \/
  \/\_____/
 \/  \/
  \__/
    |
    |

無効なツリー(入力の一部ではない追加の説明付き):

\/
 \_______/
  \__   /
   | \_/    <- reachable only on with downward route
   |
_           <- multiple roots
\/          <- multiple root characters
/\          <- multiple roots
|           <- unreachable part

|
 __/
/           <- unreachable parts
|
\____/
 |  |       <- multiple roots
_\__/       <- unreachable parts (_ and \ don't connect to each other)
|

これはコードゴルフなので、最短のエントリーが勝ちます。

回答:


7

PMA /スネイル99 93

「ツリー」定義を満たす場合は1を出力し、そうでない場合は0を出力します。長方形のスペースで埋められた形式の入力が推奨さFれますが、テストで有用な不規則なバージョンをスペースで満たされた長方形に変換するのに1バイト(オプションを使用)しかかかりません。

&
\ |{(\_|\|)d=\||(\\a7|\/d|\_da7)=\\|(\\d|\/a5|\_da5)=\/|(\_lr|\|d|\/l|\\r)=\_},^_!(r.,^ )d~

ゴルフされていない、古いバージョン(私の個人的な楽しみのために):

F&
\ |
{
  \_ (lr=\_|da5=\/|da7=\\|d=\|) | \/ (l=\_|a5=\/|d=\\) | 
    \\ (r=\_|a7=\\|d=\/) | \|d=(\_|\|)    
}, 
^_ !(r.,^ ) d~

これは、現在の言語機能にかなり適していることがわかりました。残念ながら、参照カウントのバグが機能する前に、数時間かけて参照カウントのバグを追跡しなければなりませんでした。

この&オプションは、すべての文字で一致する必要があることを意味します。スペース以外の各開始点から、下への下降パスをチェックします。正規表現を使用して有限状態マシンを作成することは、ここでアサーションを使用することにより幸運にもずっと短くなり=ます。一番下の行で、右側にスペース以外の文字がないことを確認します。


10

Mathematica、345 300バイト

まだかなり長いですが、それは始まりだと思います...

(s=StringSplit;v=Reverse;#=="|"||#=="\\"||#=="/"&[""<>s@#]&&(g={};i=0;(c={i,++j};d={i,j+1/2};e=2d-c;g=Join[g,Switch[#,"|",{d->{1,0}+d},"/",{c->c+1},"\\",{e->{i+1,j}},"_",{c->d,d->e,e->c},_,{}]])&/@Characters[++i;j=0;#]&/@{##};Sort@VertexOutComponent[Graph@g,g[[1,1]]]==Union@@List@@@g)&@@v@s[#,"
"])&

これは、わずかに未使用のバージョンです。

(
  s = StringSplit;
  v = Reverse;
  # == "|" || # == "\\" || # == "/" &[
      "" <> s@#
      ] && (
      g = {};
      i = 0;
      (
           c = {i, ++j};
           d = {i, j + 1/2};
           e = 2 d - c;
           g = Join[g, Switch[#,
              "|", {d -> {1, 0} + d},
              "/", {c -> c + 1},
              "\\", {e -> {i + 1, j}},
              "_", {c -> d, d -> e, e -> c},
              _, {}
              ]]
           ) & /@ Characters[
          ++i;
          j = 0;
          #
          ] & /@ {##};
      Sort@VertexOutComponent[Graph@g, g[[1, 1]]] == 
       Union @@ List @@@ g
      ) & @@ v@s[#, "\n"]
) &

これは、入力として文字列を受け取り、Trueまたはを返す名前のない関数を定義しますFalse

基本的な考え方は、最初に単一のルートがあることを確認してから、実際の(有向)Graphオブジェクトを作成して、ルートからすべての頂点に到達できるかどうかを確認することです。グラフの作成方法は次のとおりです。

ASCIIアートに整数グリッドがオーバーレイされていることを想像してください。整数座標は文字セルの角に対応します。次に、各セルに、接続可能な6つの関連ポイントがあります。以下に例を示します。ここでも、ポイントaにラベルを付けていfます。

     |                 |
     |                 |
---(2,3)---(2.5,3)---(3,2)---
     | d      e      f |
     |                 |
     |                 |
     |                 |
     |                 |
     |                 |
     |                 |
     | a      b      c |
---(2,2)---(2.5,2)---(3,2)---
     |                 |
     |                 |

そのため、頂点がこれらの半整数座標であり、エッジが入力内の非スペース文字によって決定されるグラフを作成できます。|に接続be/接続af\接続cdます。グラフを後で移動するときに下方向に移動しないように、これらは有向エッジでなければならないことに注意してください。以下のために_私たちはどちらかの道を行くことができるので、理論的には、我々は4辺を必要としますa -> bb -> ab -> cc -> b。しかし、我々は重要なことのすべては、我々は3つのエッジにこれを短縮することができるように、すべての3つの頂点を含むサイクルがあることであることに気づくことができます:a -> bb -> cc -> a

Mathematicaでは、このグラフの作成は非常に簡単です。なぜなら、どのオブジェクトも頂点として機能できるため、頂点座標ペアであるグラフを実際に作成できるからです。

最後に、ルートからすべての頂点に到達できることを確認します。ルートの座標は、グラフに追加した最初の頂点として簡単に見つかります。次に、すべての頂点に到達できるかどうかを確認する最短の方法VertexOutComponentは、ルートのルート(ルートから到達可能なすべての頂点のセット)がグラフ内のすべての頂点のセットと同一かどうかを確認することです。


1
300バイトは長いかもしれませんが、正確に 300バイトで十分です!
アレックスA.

2

ルビー226227228

->i{w=i.index(?\n)+1
t=[i.index(/[^ _] *\n\z/)]
a=->x,c{(i[x]==c||i[x]==?_)&&t<<x}
((x=t.pop)&&(s=x-w;c=i[x])<?0?(a[s+1,?/];a[s,?\\]):c<?]?(a[s-1,?\\];a[s,?/]):c<?`?(a[x-1,?\\];a[x+1,?/]):a[s,?|]
i[x]=' ')while t!=[]
!i[/\S/]}

オンラインテスト:http : //ideone.com/Z7TLTt

プログラムは次のことを行います。

  • ルートを検索し(\/または|最後の行に)
  • そのルートから始まり、ルールを使用してツリーを登り、すべての訪問された文字をスペースに置き換えます
  • 最後に、文字列が完全に空白(有効なツリーを意味する)で構成されているかどうか(無効なツリー。すべてのピースが「訪問」されているわけではない)を確認します。

ここでは、無料です:

F =-> input {
  row_size = input.index(?\n)+1

  root_coord = input.index /[^ _] *\n\z/

  # coordinates to process
  todo = [root_coord]

  add_todo = -> coord, char{
    if input[coord] == char || input[coord] == ?_
      todo << coord
    end
  }

  while todo.any?
    x = todo.pop

    next unless x # exit quickly if no root present

    case input[x]
    when ?|
      add_todo[x - row_size, ?|]
    when ?_
      add_todo[x - 1, ?\\]
      add_todo[x + 1, ?/]
    when ?/
      add_todo[x - row_size + 1, ?/]
      add_todo[x - row_size, ?\\]
    when ?\\
      add_todo[x - row_size - 1, ?\\]
      add_todo[x - row_size, ?/]
    end
    input[x]=' '
  end
  input.strip < ?*
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.