스택 교환


23

문제

S 1 ~ S N 이라는 N 개의 스택 이 있고 각 S k (k = 1 ~ N)에 숫자 k의 N 복사본이 포함되어 있다고 가정 해보십시오.

예를 들어 N = 3 인 경우 스택은 다음과 같습니다.

1  2  3  <- top of stack
1  2  3
1  2  3  <- bottom of stack
=======
1  2  3  <- stack index

여기에는 1, 2 및 3으로 인덱스 된 3 개의 스택이 있으며 각 스택에는 자체 인덱스의 N 개의 인스턴스가 있습니다.

목표는 각각의 스택이 위에서 아래로 순서대로 1에서 N까지의 숫자를 동일하게 포함하도록 N 스택을 재정렬하는 것입니다.

예를 들어 N = 3의 경우 목표는 스택을 다음과 같이 재배 열하는 것입니다.

1  1  1
2  2  2
3  3  3
=======
1  2  3

스택으로 수행 할 수있는 유일한 작업은 스택 중 하나에서 최상위 번호를 가져와 (포핑) 즉시 다른 스택 위에 배치하는 것입니다 (푸싱) . 이것은 다음 규정에 따릅니다.

  • 해당 스택의 최상위 숫자보다 작거나 같은 경우에만 숫자를 스택에 푸시 할 수 있습니다.

    • 예에서는 1기호가있는 스택으로 푸시 될 수있다 1, 2또는 3상단되지만은 2오직 함께 스택에 푸시 할 수 2또는 3상단에 (또는 그 이상).

    • 이는 스택이 항상 단조 증가 하는 효과가 있습니다.

  • 비어 있지 않은 스택은 팝될 수 있으며, 이전 글 머리표가 만족되는 것으로 가정하면 모든 스택이 푸시 될 수 있습니다.

  • 빈 스택에 숫자를 넣을 수 있습니다.

  • 스택에는 최대 높이 제한이 없습니다.

  • 스택은 생성하거나 파괴 할 수 없으며 항상 N 개가 있습니다.

이 과제는 스택 교환을 완료하기 위해 팝과 푸시를 결정하는 것입니다. 반드시 최소한의 움직임이 아닌 확실한 방법으로해야합니다.

(갑판으로 연습하는 것이 문제에 대한 느낌을 얻는 좋은 방법입니다.)

도전

양의 정수 N을 취하고 3 이상으로 보장되는 프로그램이나 함수를 작성하십시오. 스택을 초기 상태에서 재정렬하는 데 필요한 모든 팝 푸시 동작을 나타내는 문자열을 인쇄하거나 반환하십시오.

1  2  3  4  5
1  2  3  4  5
1  2  3  4  5
1  2  3  4  5
1  2  3  4  5
=============
1  2  3  4  5

(N = 5 건)

최종 상태로 :

1  1  1  1  1
2  2  2  2  2
3  3  3  3  3
4  4  4  4  4
5  5  5  5  5
=============
1  2  3  4  5

출력의 모든 줄은 공백으로 구분 된 두 개의 숫자를 포함해야합니다. 첫 번째 숫자는 팝할 스택의 인덱스이고 두 번째 숫자는 푸시 할 스택의 인덱스입니다. 모든 라인의 동작을 순서대로 수행하면 규칙을 어 기지 않고 스택을 올바르게 정렬해야합니다.

예를 들어, 다음은 N = 3 경우에 유효한 잠재적 출력입니다.

1 2  [move the top number on stack 1 to the top of stack 2]
1 2  [repeat]
1 2  [repeat]
3 1  [move the top number on stack 3 to the top of stack 1]
2 3  [etc.]
2 3
2 3
2 1
2 1
2 1
3 1
3 1
3 1
3 2
1 2
1 2
1 2
1 3
2 3
2 3
2 3
1 2
3 2
3 1

노트

  • 출력은 최적필요 없으며 정확해야합니다. 즉, 팝 및 푸시 횟수를 최소화 할 필요가 없습니다.

    • 예를 들어, 어떤 움직임이 반복적으로 발생하고 즉시 반대로 바뀌면 괜찮을 것입니다.
    • 예를 들어 2 2, 한 번의 이동으로 동일한 스택을 퍼핑하고 밀어 넣는 것도 허용됩니다 (물론 무의미 함).
  • 결과 결정적이고 유한해야합니다.

  • 스택에는 1 기반 인덱싱이 있습니다. 0 기반 인덱싱은 허용되지 않습니다.

  • 9보다 큰 N은 물론 한 자릿수 N과 마찬가지로 작동해야합니다.

  • 원하는 경우 공백과 줄 바꾸기 대신 숫자가 아닌 두 개의 인쇄 가능한 ASCII 문자를 사용할 수 있습니다 . 출력에서 후행 줄 바꿈 (또는 줄 바꿈 대체)이 좋습니다.

채점

바이트 단위의 가장 짧은 코드가 이깁니다. Tiebreaker가 더 높은 투표 응답입니다.

알고리즘이 최적임을 보여줄 수 있다면 무가치 한 브라우니 포인트.


"작은 것들에 대한 추가 점수"말도 안되는
말로 멈추기

18
@ zyabin101 당신은 브라우니에서 기회를 잃었습니다.
Calvin 's Hobbies

9
당신은 항상 멋진 타이틀을 생각해냅니다!
Luis Mendo

@HelkaHomba-._(._.)_.-
user48538

N=3최적 의 경우에 포함 할 수있는 출력이 있습니까?
R. Kap

답변:


9

Pyth 96 94 바이트

Mt*Q+++bGdHM|%+y_GHQQg1 2++Qd1g2 3g2 1g3 1++Qd2Vr3QgNtN++QdN;g1QVStQVStQI<NHgnNHnNtH)++nN0dnNH

여기 사용해보십시오

어떻게 작동합니까?

이 설명은 N = 5를 사용합니다.

1 부 : 모든 스택에서 맨 아래 레이어 만들기

이것이 별도의 코드 조각을 필요로하는 이유는 모든 스택을 사용해야하기 때문입니다. 첫 번째 4는 그 아래에 5를 넣고 마지막 스택은 5를 제공해야합니다. 즉, 4를 모두 어딘가로 옮기고 거기에 5를 넣고 4를 뒤로 옮길 수는 없습니다.

시각화 : (괄호는 이동할 내용을 의미)

     _
11111 |
22222 |_ Can't move 4s here, not monotonically increasing
33333_|
(44444)------------??? Where to put the 4s?
55555 <- Must supply the 5 that will be moved

대신,이 첫 번째 교환을 수행하려면 먼저 모든 1을 두 번째 스택으로 이동하고 5를 첫 번째 스택으로 이동 (현재 비어 있음)하고 1을 세 번째 스택으로 이동하고 2를 첫 번째로 이동합니다 1을 다시 첫 번째 스택으로 옮기고 마지막으로 5를 두 번째 스택으로 옮기십시오.

(11111)-----.
2222211111<-'
===============================
5<---------.
2222211111 : (from stack 5)
===============================
5
22222(11111)-.
3333311111<--'
===============================
522222<-.
(22222)-'
3333311111
===============================
52222211111<-.
             |
33333(11111)-'
===============================
52222211111
5<-----.
33333  |
44444  |
555(5)-'

이제 스택을 이동할 수있는 여유 공간이 생겼으므로 (올바른 지점에 배치 된 5 만 포함하는 스택 2) 스택 3으로 모든 3을 이동하고 스택 3에 5를 배치 할 수 있습니다. 스택 4의 경우와 동일하며 이제 5를 모두 올바른 위치에 가져옵니다! 그리고 한가지 더 : 우리는 모든 1을 스택 5로 이동시켜 다음 스택 교환을위한 멋진 설정을 얻습니다.

522222(11111)-.
533333        |
544444        |
5             |
511111<-------'

2 부 : 다른 모든 작업 수행 :)

이제는 훨씬 쉬워졌습니다. 이제 우리는 항상 다른 숫자를 움직일 수있는 무료 스택을 가지고 있기 때문입니다. 먼저 우리는 4가 어디에 있는지 알아냅니다. 약간의 검사를 통해 시작한 위치에서 항상 1 위 또는 마지막 스택 위의 2 위에 있음을 알 수 있습니다. 이제 스택을 계속 내려 가고 스택이 비어 있으면 스택에 4를 배치하고 그렇지 않으면 스택에 다른 숫자를 1 개 위로 이동합니다. 이제 우리는 4 개를 모두 갖추 었습니다.

522222<------.
533333<----. |
544444-.-.-'-'
5<-----' |
511111<--'
===============================
5433333
54
54
5411111
5422222

이제 우리는 3s가 4s보다 2 스택 이상이라는 것을 알고 있습니다. 이것은 우리가 4s와 똑같은 일을 할 수 있다는 것을 의미합니다! 그리고 스택 인덱스를 다른쪽으로 감싸는 한 계속해서이 작업을 수행 할 수 있습니다.

5433333-'wrap around 543
54                   543
54                   54311111
5411111 .----------->54322222
5422222 |2 stacks up 543

따라서 모든 스택을 교환 할 때까지이 작업을 계속 수행 할 수 있습니다.

코드 설명 :

우선 : (중요한) 사전 정의 된 변수.

Q: Evaluated input.
b: The newline character, '\n'
d: A space, ' '

2 개의 람다 정의가 있습니다.

M           | g(G)(H), used for moving Q numbers at a time.
            | We will call these Q numbers a "(number) block"
 t          | Tail, used to remove beginning newline
  *Q        | Repeat the following Q times
    +++bGdH | '\n' + G + ' ' + H. Just a whole bunch of concatenating.
            |
M           | n(G)(H), used for figuring out which stacks to move from
 |       Q  | If the following code is 0 (false), then use Q instead
  %     Q   | Mod Q
   +   H    | Add H
    y       | Multiply by 2
     _G     | Negate (remember in the explanation part 2? Always 2 stacks above?)

스택 교환 : 1 부

g1 2                       | Move the 1 block to stack 2
    ++Qd1                  | Move a Q to stack 1
         g2 3              | Move the 1 block to stack 3
             g2 1          | Move the 2 block to stack 1
                 g3 1      | Move the 1 block back to stack 1
                     ++Qd2 | Move a Q to stack 2
 v---Code-continuation---' |I don't have enough room!!!
Vr3Q                       | For N in range(3, Q)
    gNtN                   | Move the number block in stack N up 1
        ++QdN              | Move a Q to stack N
             ;g1Q          | End for loop; move the 1 block to the last stack

스택 교환 : 2 부

VStQ                           | For N in [1, 2, ..., Q - 1]
    VStQ                       | For H in [1, 2, ..., Q - 1]
        I<NH                   | If N < H
            g                  | Number block move
             nNH               |  (find number block)
                nNtH           |  (find the previous stack)
                    )          | End "For H"
                     ++nN0dnNH | Find start, move number to next location down

나는 이미 브라우니 포인트를 얻지 못한다는 것을 알고 있습니다.

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