선형화 된 트리입니까? (빵 초판)


11

배경

레이블이없는 트리는 다음과 같습니다.

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

이 트리 를 선형화 하기 위해 먼저 각 노드 o에 여러 개의 자식 노드로 레이블 을 지정합니다.

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

그런 다음 한 줄씩, 왼쪽에서 오른쪽으로 의미하는 호흡 우선 순위로 목록에 숫자를 씁니다.

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

이것은 위의 트리를 독특하고 모호하지 않은 표현으로, 두 개의 다른 순수 트리가 동일한 선형화를 가지지 않으며 목록에서 원래 트리를 재구성 할 수 있음을 의미합니다.

각 트리가 특정 정수 목록에 해당하지만 각 정수 목록이 유효한 선형화 된 트리를 [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

직무

정수 목록이 제공되면 가능한 적은 바이트를 사용하여 트리의 유효한 선형화 여부를 결정하십시오. 당신은 전체 프로그램이나 함수를 작성할 수 있습니다.

입력 : 음이 아닌 정수로 구성된 비어 있지 않은 목록입니다.

출력 : 목록이 트리의 선형화이면 참 값이고, 그렇지 않으면 거짓 값입니다.

테스트 케이스

Truthy
[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

하스켈, 44 바이트

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

g리스트를 가져 와서 불리언을 리턴 하는 함수 를 정의합니다 . 모든 테스트 사례를 통과했는지 확인하십시오 .

설명

이것은 깊이 우선 및 너비 우선 선형화가 동일한 배열을 생성한다는 사실에 의존합니다. 자세한 내용은 Martin의 답변을 참조하십시오. 기본적으로 그들은 배열에서 동일한 산술 조건을 제공합니다.

이 함수 f에는 입력 목록이 단일 목록으로 묶여 있습니다. n목록에서 하나의 숫자를 팝한 다음 n나머지 목록에서 시간 을 호출 하여 팝된 노드의 하위를 처리합니다 (먼저 깊이). 빈 목록을 팝하면 []오류 상태로 사용됩니다. 이 함수 g는 최종 결과가 [[]]처리되지 않은 노드가없는 고유 한 오류가없는 상태 인지 확인합니다 . Haskell을 약하게 입력했다면 0오류 상태로 사용할 수 있으며 다른 목록으로 입력을 감쌀 필요가 없습니다.


3

수학, 38 바이트

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

기본 아이디어는 채울 노드 수를 추적하는 것입니다. 목록의 각 요소는 하나의 노드를 사용하고 하위 노드 수만큼을 추가합니다. 따라서 각 요소 i는 총 개수를로 변경합니다 i-1. 이 개수는 1 개가 1아닙니다 0. 왜냐하면 루트가 아닌 (루트) 부터 시작해야하기 때문 입니다.

트리가 유효하기 위해서는 0a) 현재 노드를 배치 할 위치가없고 b) 끝으로 끝나야하기 때문에 목록 전체에서 아래로 내려갈 수 없습니다 -1. 그렇지 않으면 사용하지 않는 노드가 남아 있습니다.

Accumulate[#-1]입력 노드 의 접두사 합계에서 1을 뺀 값 으로 나머지 노드의 누적 합계를 얻습니다 . 그런 다음 마지막 요소와 마지막 요소 만 포함 되어 있는지 확인합니다 -1.

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

마지막 요소가 음수인지 확인하는 것만으로도 충분합니다.을 (를) 초과하여 감소시킬 수 없으므로 1마지막 값이 -2이보다 작거나 같으면 최소값이 음수가 아닌 것은 불가능합니다.


2

망막 , 29 바이트

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

온라인으로 사용해보십시오! 첫 번째 줄은 줄 바꿈으로 구분 된 테스트 스위트를 활성화합니다.

설명

기본 아이디어는 나의 Mathematica 답변 과 동일합니다 : 우리는 남아있는 노드의 누적 합계를 추적하여 결코 0 이하로 떨어지지 않고 0으로 끝나는 지 확인합니다. 그러나 이것이 정규식으로 구현되는 방식은 매우 다릅니다.

\d+
$*

이것은 단순히 입력을 단항으로 변환하여 각 정수 nn1 로 바꿉니다.

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

이것이 진정한 마술이 일어나는 곳입니다. 유효한 트리에만 일치하는 상당히 짧은 정규식이지만 역학은 매우 미묘합니다.

균형 그룹 을 사용하여 노드 수를 추적하고 있는데, 이는 정규식 내의 스택으로 작업하는 방법입니다.

우선, 그러한 스택은 절대로 음의 깊이를 가질 수 없으므로 -1Mathematica 솔루션에서와 같이 결국에는 끝 으로 표현할 수 없습니다 . 그러나, 우리는 입력의 마지막 요소가 있습니다 할 수 있다 유효한 스택에 제로로 (그렇지 않으면 우리는 끝낼 수 없었다 -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@{+\(_{\}&}/|!}내 생각 엔?
Martin Ender

또한 전체 프로그램을 사용하여 바이트를 절약 할 수 있어야합니다 @.
Martin Ender

1

미로 , 17 바이트

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

온라인으로 사용해보십시오!

정확한 출력이 -1있고 잘못된 출력이 비어 있습니다. 미로에서 진실과 허위를 정의하는 것은 약간 까다 롭습니다. 미로의 가지가 주로 삼항이기 때문입니다. 그러나 두 개의 브랜치를 사용하여 조건부를 구성하는 유일한 방법은 다음과 같습니다.

>"F
 T

이 경우, 나는 (가동 방향에 영향을 미치지 않기 때문에) 거짓으로 똑바로 움직이고 진실을 돌리는 것을 고려할 것입니다. 이들은 각각 0과 0이 아닙니다. 빈 출력을 사용하여 0을 나타내는 이유는 출력을 다른 Labyrinth 프로그램으로 다시 파이프하는 경우 입력 연산자 ?가 입력이 비어 있으면 실제로 0을 푸시하므로 빈 문자열을 유효한 것으로 간주하기 때문입니다 제로의 표현.

설명

알고리즘은 여전히 ​​Mathematica 및 Retina 답변과 동일하지만 Labyrinth의 제어 흐름으로 인해 이번에는 약간 다르게 작동합니다.

  • 여기서는 총 카운터를 하나씩 사용하지 않습니다. 대신 a) 음수 카운터로 작업하고 b) -11처음에 초기화 하여 카운터가 목록 전체에서 음수가되도록하고 마지막 입력에서 0을 누르십시오. 이것은 실제로 제어 흐름을 단순화시킵니다.
  • 전체 목록을 작성하고 잘못된 값이 포함되어 있는지 확인하는 대신 가능한 세 가지 종료 조건이 있습니다.

    1. 우리는 총 카운트 0에 도달하기 전에 EOF를 쳤다. 이 경우 사용하지 않는 노드가 남아 있고 아무것도 인쇄하지 않습니다.
    2. 우리는 제로에 도달 하고 우리는 EOF에있어. 이 경우 유효한 트리가 있습니다.
    3. 우리는 0에 도달하고 아직 EOF에 있지 않습니다. 이 경우 모든 요소를 ​​다루기 전에 노드가 부족하여 아무 것도 인쇄하지 않습니다.

실제 코드는 왼쪽 상단에서 시작합니다. 은 ((A) 내로 스택의 상단에 내재 제로 턴 -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.

그것은 우리가 어떤 시점에서 누적 합계를 0으로 줄인 경우에만 남습니다. IP는 오른쪽 아래로 이동하여 ,EOF에 도달했는지 확인하기 위해 다른 문자를 읽습니다. 그렇지 않으면 값이 양수이고 IP가 서쪽을 향해쪽으로 향하고 @프로그램이 종료됩니다. EOF에 도달하면 IP가 동쪽으로 바뀌고 -1with를 인쇄합니다 !. 그런 다음 IP는 @프로그램을 종료하기 위해 약간 이상한 경로를 통해 왼쪽 하단으로 웜합니다 .


0

파이썬, 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
Kade

^ 이와 관련, 당신의 몸을 변경할 수 allx<len(l)-y for y,x in enumerate(l)(68)에 그걸 얻기 위해 또 다른 2 바이트를 저장
카데

나는 이것이 정확한 해결책이라고 생각하지 않기 때문에 지금 더 이상 골프를 치지 않을 것입니다. 팁 주셔서 감사합니다.
Sparr

0

Pyth, 13 바이트

qxsM._tMQ_1tl

입력 표현의 모든 지점에서 트리의 현재 채워짐을 계산하는 것으로 시작합니다. 아이디어의 그 부분은 Martin Ender로부터 크게 빌려 왔습니다.sM._tMQ

이 목록이 있으면 -1( x..._1)를 포함하는 첫 번째 색인 이 입력 길이에서 1을 뺀 길이 인지 확인합니다 q...tl(Q).

그것이 효과가 있다고 생각하지 않습니까? 직접 해보십시오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.