这是一棵真正的树吗?


20

您应该编写一个程序或函数来接收字符串作为输入,然后输出或返回(如果输入是ASCII树)。

  _
\/  /
 \_/
  |
  |

ASCII树由字符/ \ | _ spaces和组成newlines

非空白字符通过线段连接其单元格的两个边缘点:

  • / 连接左下角和右上角
  • \ 连接右下角和左上角
  • | 连接底边和顶边的中点
  • _ 连接左下角和右下角以及底边的中点

(请注意,这意味着|只能连接|_但不与/\)。

如果遵循以下规则,则ASCII图片称为树:

  • 恰好一个字符的一个点(根)碰到最后一行的底部边缘。
  • 您可以通过以下方式到达任何线段的任意点:

    • 从根开始
    • 仅使用线段
    • 永远不要朝下(甚至不向侧面)

输入值

  • 一个由字符组成/ \ | _ space并且newline包含至少一个非空白字符的字符串。
  • 您可以选择两种输入格式:

    • 树周围没有不必要的空格(如示例所示)。
    • 除了行右侧的空格使所有行具有相同的长度外,树周围没有不必要的空格(如示例所示)。
  • 尾随换行符是可选的。

输出量

  • 如果输入是ascii树,则为一致的真实值。
  • 一致的falsy如果输入不是一个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)
|

这是代码高尔夫球,因此最短的条目将获胜。

Answers:


7

PMA /蜗牛99 93

如果满足“树”定义,则打印1;否则,则打印0。最好使用矩形空格填充的输入形式,尽管只需花费一个字节(使用F选项)即可将衣衫version的版本转换为空格填充的矩形,这在测试中很有用。

&
\ |{(\_|\|)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"]
) &

这定义了一个未命名函数,该函数将字符串作为输入并返回Trueor False

基本思想是首先检查是否有单个根,然后构建一个实际的(有向)Graph对象以检查是否可以从该根到达所有顶点。这是我们构建图形的方式:

想象一下一个覆盖在ASCII图形上的整数网格,其中整数坐标对应于字符单元的角。然后,在每个单元上可以连接六个相关点。下面是一个例子,在这里我也标记点af

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

因此,我们可以构建一个图形,其顶点是这些半整数坐标,并且其边线由输入中的非空格字符确定。|连接be/连接af\连接cd。请注意,这些必须是有方向的边,以确保我们在以后遍历图形时永远不会向下移动。对于_我们可以去任何一种方式,因此从理论上讲,我们需要四个边缘a -> bb -> ab -> cc -> b。但是,我们可以看到,真正重要的是,有一个包含所有三个顶点,所以我们可以缩短这三条边一个循环:a -> bb -> cc -> a

在Mathematica中,构建该图非常简单,因为任何对象都可以充当顶点,因此我实际上可以构建一个顶点坐标对的图。

最后,我们检查是否可以从根到达每个顶点。根的坐标很容易找到,它是我们添加到图形中的第一个顶点。然后,我发现检查是否可以到达所有顶点的最短方法是检查VertexOutComponent根的顶点(即从根可到达的所有顶点的集合)是否与图中所有顶点的集合相同。


1
300个字节可能很长,但恰好 300个字节就足够了!
Alex A.

2

红宝石226 227 228

->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 < ?*
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.