S와 K

시간 제한3초메모리 제한128 MB

요약
S와 K로 이루어진 이진 트리가 주어질 때 두 규칙을 더 이상 적용할 수 없을 때까지 반복 적용한 뒤 최종 트리 문자열을 출력한다.
난이도

보통10점 중 7점

유형
구현, 시뮬레이션, 트리, 재귀
정답자
아직 제출이 없습니다

문제

유용한 계산을 수행할 수 있는 가장 단순한 컴퓨터는 어떤 모습일까? 오랫동안 이론 전산학자들은 튜링 기계나 람다 대수처럼 여러 단순한 계산 모델을 고안해 왔다. 이 문제에서는 1924년 Moses Schönfinkel이 고안한, 단 두 글자 SS와 KK만으로 이루어진 더욱 단순한 체계를 살펴본다. 이 글자들을 구조화하기 위해 이진 트리로 배열하며, 트리의 모든 잎 노드는 SS 또는 KK 중 하나이다.

이러한 이진 트리는 다음과 같이 문자열로 인코딩한다. 잎 노드는 SS 또는 KK로 쓴다. 잎이 아닌 내부 노드는 (ab)(ab)로 쓰며, aa는 왼쪽 자식의 문자열, bb는 오른쪽 자식의 문자열이다. 예를 들어, 어떤 트리는 문자열 ((SK)K)((SK)K)로 표현된다.

트리는 아래 규칙을 반복 적용하여 변환한다. 매 단계마다 규칙을 주어진 순서대로, 즉 규칙 (1)을 먼저, 그다음 규칙 (2)를 시도하며, 어떤 규칙이 변환을 수행하자마자 전체 트리의 루트에서 다시 규칙 (1)부터 검사를 시작한다.

  1. 트리가 ((Ka)b)((Ka)b) 형태이고 aa, bb가 임의의 부분 트리일 때, 전체를 부분 트리 aa로만 바꾼다.
  2. 트리가 (((Sa)b)c)(((Sa)b)c) 형태이고 aa, bb, cc가 임의의 부분 트리일 때, ((ac)(bc))((ac)(bc))로 바꾼다. 이는 aa와 bb를 각각 한 번씩, cc를 두 번 포함한다.
  3. 위 두 규칙을 현재 노드에서 적용할 수 없으면, 현재 노드의 왼쪽 자식 부분 트리에 이 규칙들을 재귀적으로 적용한다.
  4. 그래도 적용할 수 없으면, 현재 노드의 오른쪽 자식 부분 트리에 이 규칙들을 재귀적으로 적용한다.
  5. 어느 곳에서도 규칙을 적용할 수 없으면, 결과 트리의 문자열 표현을 출력하고 멈춘다.

이 단순한 규칙들로 어떻게 계산을 하는가? 먼저 자연수의 표현을 정한다. 여러 방법이 가능하지만, Alonzo Church가 고안한 방식이 가장 널리 쓰인다. 0을 0=(K((SK)K))0 = (K((SK)K))로, 다음 수 연산자를 σ=(S((S(KS))K))\sigma = (S((S(KS))K))로 정의한다. 그러면 자연수는 1=(σ0)1 = (\sigma 0), 2=(σ1)2 = (\sigma 1), 3=(σ2)3 = (\sigma 2), … 와 같이 정의되며, σ\sigma나 00 같은 기호를 우리가 정의한 부분 트리로 매번 치환한다. 따라서 수 44는 다음 트리로 표현된다

4=((S((S(KS))K))((S((S(KS))K))((S((S(KS))K))((S((S(KS))K))(K((SK)K))))))\displaystyle 4 = ((S((S(KS))K))((S((S(KS))K))((S((S(KS))K))((S((S(KS))K))(K((SK)K))))))

이 트리에는 부분 트리 σ\sigma가 네 번 나타난 뒤 부분 트리 00이 따른다. 이렇게 인코딩된 수들은 다음 부분 트리로 더할 수 있다

+=((S((SK)K))(K(S((S(KS))K))))\displaystyle + = ((S((SK)K))(K(S((S(KS))K))))

예를 들어 ++, 33, 44를 각각의 부분 트리로 치환하여 트리 ((+3)4)((+3)4)를 만들고 변환 규칙을 적용하면, 결국 수 77을 나타내는 트리에 도달한다. 곱셈은 더 간단한 부분 트리 \*=((S(KS))K)\* = ((S(KS))K)로 할 수 있다. 다만 \*\* 같은 연산자가 만들어 내는 결과는 같은 방식으로 동작하더라도 위에서 정의한 수와 글자 그대로 같아 보이지 않을 수 있다. 이때 정규화 연산자

N=((S((S((SK)K))(K(S((S(KS))K)))))(K(K((SK)K))))\displaystyle N = ((S((S((SK)K))(K(S((S(KS))K)))))(K(K((SK)K))))

를 적용하면 동치인 수들을 같은 모습으로 만들 수 있다. 예를 들어 트리 (N((\*2)4))(N((\*2)4))에 변환 규칙을 적용하면 수 88을 나타내는 트리가 된다.

조금 더 손을 보면 비교, 조건문, 재귀처럼 프로그래밍 언어에서 기대할 만한 다른 연산을 위한 트리도 만들어 더 복잡한 프로그램을 작성할 수 있다. 예를 들어 다음 트리는 팩토리얼을 계산한다:

\displaystyle \begin{align\*} ! &= ((((SS)K)((S(K((SS)(S((SS)K)))))K))((S(K(S((S((S((S((SK)K))(K(K(K((SK)K)))))) \\\ &\mathrel{\phantom=} (KK)))(K((S((S(KS))K))(K((SK)K))))))))((S(K(S((S(KS))K))))((S((S(KS))K)) \\\ &\mathrel{\phantom=} (K((S(K(S(K(S(K((S((SK)K))(K(K((SK)K))))))))))((S((S(KS))((S(K(S(KS)))) \\\ &\mathrel{\phantom=} ((S(K(S(KK))))((S((S(KS))K))(K((S((S(KS))((S(K(S(K((S((S(KS))((S(KK))((S(KS)) \\\ &\mathrel{\phantom=} ((S(K(S((SK)K))))K)))))(KK))))))((S((S(KS))K))(K((S((SK)K))(KK))))))) \\\ &\mathrel{\phantom=} (K((S((SK)K))(KK))))))))))(K(K((S((S((S(KS))((S(KK))((S(KS)) \\\ &\mathrel{\phantom=} ((S(K(S((SK)K))))K)))))(KK)))((SK)K))))))))))) \end{align\*}

이것을 정규화 연산자 및 수 44와 결합하여 트리 (N(!4))(N(!4))에 변환 규칙을 적용하면, 2424 (즉 4!4!)를 나타내는 트리가 된다.

입력

입력은 트리를 나타내는 여러 문자열로 이루어지며, 한 줄에 트리 하나씩 주어진다. 입력 한 줄은 10001000자를 넘지 않는다. 입력의 마지막 줄은 빈 줄이다.

출력

마지막 빈 줄을 제외한 각 입력 줄에 대해, 더 이상 변환이 불가능할 때까지(규칙 5) 주어진 트리에 변환 규칙을 반복 적용한 뒤, 결과 트리의 문자열 표현을 한 줄에 출력한다. 참고로 다음과 같은 일부 트리는

(((S((SK)K))((SK)K))((S((SK)K))((SK)K)))\displaystyle (((S((SK)K))((SK)K))((S((SK)K))((SK)K)))

규칙을 영원히 적용할 수도 있으나, 그러한 트리는 테스트 데이터에 포함되지 않는다.

예제4

  1. 예제 1

    입력
    ((KS)K)
    ((KK)S)
    (((SK)S)K)
    (((SS)K)S)
    (((SK)K)K)
    ((((S((SK)K))(K(S((S(KS))K))))((S((S(KS))K))(K((SK)K))))((S((S(KS))K))(K((SK)K))))
    (((S((S((SK)K))(K(S((S(KS))K)))))(K(K((SK)K))))(((S((S(KS))K))((SK)K))((S((S(KS))K))((SK)K))))
    
    
    예상 출력
    S
    K
    K
    ((SS)(KS))
    K
    ((S((S(KS))K))((S((S(KS))K))(K((SK)K))))
    ((S((S(KS))K))((S((S(KS))K))((S((S(KS))K))((S((S(KS))K))(K((SK)K))))))
    
  2. 예제 2

    입력
    S
    K
    
    
    예상 출력
    S
    K
    
  3. 예제 3

    입력
    (SK)
    (KS)
    ((SK)K)
    ((SS)(KS))
    
    
    예상 출력
    (SK)
    (KS)
    ((SK)K)
    ((SS)(KS))
    
  4. 예제 4

    입력
    (((SK)K)S)
    (((SK)K)K)
    
    
    예상 출력
    S
    K