Đây có phải là cây thật không?


20

Bạn nên viết một chương trình hoặc hàm nhận chuỗi dưới dạng đầu vào và đầu ra hoặc trả về nếu đầu vào là cây ASCII.

  _
\/  /
 \_/
  |
  |

Cây ASCII bao gồm các ký tự / \ | _ spacesnewlines.

Các ký tự không phải khoảng trắng kết nối hai điểm cạnh của các ô của chúng bằng một phân đoạn dòng:

  • / kết nối góc dưới bên trái và trên cùng bên phải
  • \ kết nối góc dưới bên phải và trên cùng bên trái
  • | kết nối các điểm giữa của cạnh dưới và cạnh trên
  • _ kết nối góc dưới bên trái và dưới cùng bên phải và điểm giữa của cạnh dưới

(Lưu ý rằng điều này có nghĩa là |chỉ có thể kết nối với |hoặc _không có /hoặc \.)

Một hình ảnh ASCII được gọi là cây nếu áp dụng các quy tắc sau:

  • Chính xác một điểm (gốc) của chính xác một ký tự chạm vào cạnh dưới cùng của hàng cuối cùng.
  • Bạn có thể đạt đến bất kỳ điểm nào của bất kỳ phân khúc dòng nào bằng cách:

    • bắt đầu từ gốc
    • chỉ sử dụng các phân đoạn dòng
    • không bao giờ đi vào một hướng đi xuống (thậm chí không đi xuống dưới)

Đầu vào

  • Một chuỗi bao gồm các ký tự / \ | _ spacenewlinechứa ít nhất một ký tự không phải khoảng trắng.
  • Bạn có thể chọn hai định dạng đầu vào:

    • Không có khoảng trắng không cần thiết xung quanh cây (như đã thấy trong các ví dụ).
    • Không có khoảng trắng không cần thiết xung quanh cây (như đã thấy trong các ví dụ) ngoại trừ khoảng trắng ở bên phải của các hàng để làm cho tất cả các hàng có cùng độ dài.
  • Trailing newline là tùy chọn.

Đầu ra

  • Giá trị trung thực nhất quán nếu đầu vào là cây ascii.
  • Một phù falsy giá trị nếu đầu vào không phải là một cây ascii.

Ví dụ

Cây hợp lệ:

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

Cây không hợp lệ (có giải thích thêm không phải là một phần của đầu vào):

\/
 \_______/
  \__   /
   | \_/    <- 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)
|

Đây là môn đánh gôn nên bài dự thi ngắn nhất sẽ thắng.

Câu trả lời:


7

PMA / Ốc , 99 93

In 1 nếu nó thỏa mãn định nghĩa "cây" hoặc 0 nếu không. Hình thức đầu vào đệm không gian hình chữ nhật được ưa thích, mặc dù chỉ tốn một byte (sử dụng Ftùy chọn) để chuyển đổi phiên bản rách rưới thành hình chữ nhật chứa đầy không gian, rất hữu ích trong thử nghiệm.

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

Ungolfed, phiên bản lỗi thời (cho niềm vui xem cá nhân của tôi):

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

Điều này hóa ra khá phù hợp với các tính năng ngôn ngữ hiện tại. Thật không may, tôi đã phải mất vài giờ để theo đuổi một lỗi đếm tham chiếu trước khi nó có thể hoạt động.

Các &tùy chọn có nghĩa là trận đấu phải thành công ở mọi nhân vật. Từ mỗi điểm bắt đầu không phải không gian, nó kiểm tra đường dẫn xuống phía dưới. Làm cho một máy trạng thái hữu hạn với một regex may mắn ngắn hơn nhiều bằng cách sử dụng các xác nhận, ở đây =.... Ở hàng dưới cùng, nó kiểm tra rằng không có ký tự không phải khoảng trắng ở bên phải.


10

Toán học, 345 300 byte

Vẫn còn khá dài, nhưng tôi đoán đó là một sự khởi đầu ...

(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[#,"
"])&

Đây là một phiên bản hơi vô căn cứ:

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

Điều này xác định một hàm không tên, lấy chuỗi làm đầu vào và trả về Truehoặc False.

Ý tưởng cơ bản trước tiên là kiểm tra xem có một gốc đơn không, và sau đó xây dựng một Graphđối tượng (có hướng) thực tế để kiểm tra xem tất cả các đỉnh có thể đạt được từ gốc hay không. Đây là cách chúng tôi xây dựng biểu đồ:

Tưởng tượng một lưới số nguyên được phủ lên nghệ thuật ASCII, trong đó tọa độ nguyên tương ứng với các góc của các ô ký tự. Sau đó, trên mỗi ô có sáu điểm liên quan có thể được kết nối. Dưới đây là một ví dụ, nơi tôi cũng đã dán nhãn các điểm ađến f:

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

Vì vậy, chúng ta có thể xây dựng một biểu đồ có các đỉnh là các tọa độ nửa nguyên này và các cạnh của chúng được xác định bởi các ký tự không phải khoảng trắng trong đầu vào. |connect bđến e, /connect ađến f\connect ctới d. Lưu ý rằng đây phải là các cạnh được định hướng để đảm bảo rằng chúng ta không bao giờ di chuyển xuống dưới trong khi di chuyển ngang qua biểu đồ sau này. Đối với _chúng ta có thể đi một trong hai cách, vì vậy về mặt lý thuyết chúng ta cần bốn cạnh a -> b, b -> a, b -> c, c -> b. Tuy nhiên, chúng ta có thể nhận thấy rằng tất cả những gì quan trọng là có một chu kỳ có chứa cả ba đỉnh, vì vậy chúng tôi có thể rút ngắn này để ba cạnh: a -> b, b -> c, c -> a.

Xây dựng biểu đồ này khá đơn giản trong Mathicala, bởi vì bất kỳ đối tượng nào cũng có thể đóng vai trò là một đỉnh, vì vậy tôi thực sự có thể xây dựng một biểu đồ có các đỉnh các cặp tọa độ.

Cuối cùng, chúng tôi kiểm tra rằng mọi đỉnh có thể đạt được từ gốc. Tọa độ của root dễ dàng được tìm thấy như là đỉnh đầu tiên mà chúng ta đã thêm vào biểu đồ. Sau đó, cách ngắn nhất mà tôi đã tìm thấy để kiểm tra xem tất cả các đỉnh có thể đạt được hay không là kiểm tra xem VertexOutComponentgốc (tức là tập hợp tất cả các đỉnh có thể tiếp cận từ gốc) có giống với tập hợp tất cả các đỉnh trong biểu đồ hay không.


1
300 byte có thể dài, nhưng chính xác 300 là rất thỏa mãn!
Alex A.

2

Ruby 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/]}

Kiểm tra trực tuyến: http://ideone.com/Z7TLTt

Chương trình thực hiện như sau:

  • tìm kiếm cho một root (một \, /hoặc |vào hàng cuối cùng)
  • bắt đầu từ gốc đó, trèo lên cây bằng cách sử dụng các quy tắc và thay thế mọi char đã truy cập bằng một khoảng trắng
  • ở cuối, hãy xem chuỗi của chúng tôi có bao gồm đầy đủ khoảng trắng (có nghĩa là cây hợp lệ) hay không (cây không hợp lệ; không phải tất cả các phần đã được "truy cập")

Đây là vô căn cứ:

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 < ?*
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.