이것이 진짜 나무입니까?


20

문자열을 입력으로 수신하고 입력이 ASCII 트리 인 경우 출력 또는 리턴하는 프로그램 또는 함수를 작성해야합니다.

  _
\/  /
 \_/
  |
  |

ASCII 트리는 문자 / \ | _ spaces와 로 구성됩니다 newlines.

공백이 아닌 문자는 셀의 두 가장자리 포인트를 선 세그먼트로 연결합니다.

  • / 왼쪽 하단과 오른쪽 상단을 연결합니다
  • \ 오른쪽 하단과 왼쪽 상단을 연결합니다
  • | 아래쪽 가장자리와 위쪽 가장자리의 중간 지점을 연결합니다
  • _ 왼쪽 하단 및 오른쪽 하단 모서리와 하단 가장자리의 중간 점을 연결합니다

(참고로이 방법 |만 연결할 수 |또는 _은 불가능 /하거나 \).

다음 규칙이 적용되는 경우 ASCII 그림을 트리라고합니다.

  • 정확히 한 문자의 정확히 한 점 (루트)이 마지막 행의 아래쪽 가장자리에 닿습니다.
  • 다음을 통해 라인 세그먼트의 어느 지점 에나 도달 할 수 있습니다.

    • 루트에서 시작
    • 선분 만 사용
    • 아래쪽으로 향하지 마십시오 (아래쪽으로도)

입력

  • 문자로 구성 / \ | _ space되고 newline공백이 아닌 문자를 하나 이상 포함 하는 문자열 입니다.
  • 두 가지 입력 형식을 선택할 수 있습니다.

    • 트리 주변에 불필요한 공백이 없습니다 (예제 참조).
    • 모든 행을 같은 길이로 만들기 위해 행의 오른쪽에 공백을 제외하고 (예에서 볼 수 있듯이) 나무 주위에 불필요한 공백이 없습니다.
  • 후행 줄 바꿈은 선택 사항입니다.

산출

  • 입력이 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~

Ungolfed, 구식 버전 (개인 시청의 즐거움을 위해) :

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

이것은 현재 언어 기능에 매우 적합한 것으로 판명되었습니다. 불행히도, 참조 카운트 버그가 작동하기 전에 추적하는 데 몇 시간을 소비해야했습니다.

&옵션은 모든 문자에서 일치해야합니다. 각 비 공간 시작점에서 아래쪽으로 내려가는 경로를 확인합니다. 정규식으로 유한 상태 머신을 만드는 것은 운 좋게도 단언을 사용하면 훨씬 짧습니다 =. 맨 아래 행에서 오른쪽에 공백이 아닌 문자가 없는지 확인합니다.


10

Mathematica, 345300 바이트

여전히 꽤 길지만 시작 인 것 같습니다 ...

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

다음은 약간 ungolfed 버전입니다.

(
  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. 나중에 그래프를 탐색하는 동안 절대 아래쪽으로 움직이지 않도록 가장자리를 향해야합니다. 들어 _우리가 어느 길을 갈 수 있기 때문에 이론적으로 우리가 네 모서리가 필요합니다 a -> b, b -> a, b -> c, c -> b. 그러나, 우리는 모든 문제는 우리가 세 가지 가장자리에이를 단축 할 수 있도록 세 꼭지점을 포함하는주기가 있다는 것을 알 수 있습니다 a -> b, b -> c, c -> 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

이 프로그램은 다음을 수행합니다.

  • 루트에 대한 검색 (A \, /또는 |마지막 행에)
  • 그 루트에서 시작하여 규칙을 사용하여 나무를 오르고 방문한 모든 문자를 공백으로 바꿉니다.
  • 마지막으로, 문자열이 공백 (유효한 나무를 의미 함)으로 구성되어 있는지 아닌지 (유효하지 않은 나무; 모든 조각이 "방문 된"것은 아닌지) 확인하십시오.

여기에 골퍼가 없습니다 :

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.