Troca de pilha

23

Problema

Digamos que você tenha N pilhas denominadas S 1 a S N , onde cada S k (k = 1 a N) contém N cópias do número k.

Por exemplo, quando N = 3, as pilhas ficam assim:

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

Aqui existem 3 pilhas indexadas como 1, 2 e 3, e cada uma contém N instâncias de seu próprio índice.

O objetivo é reorganizar as pilhas N, de modo que cada uma delas contenha os números de 1 a N de maneira idêntica, de cima para baixo.

por exemplo, para N = 3, o objetivo é reorganizar as pilhas em:

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

A única ação que você pode executar com as pilhas é pegar o número superior de uma das pilhas (estourar) e colocá-lo imediatamente no topo de uma pilha diferente (empurrar) . Isso está sujeito a estas estipulações:

  • Um número só pode ser enviado para uma pilha se for menor ou igual ao número superior nessa pilha.

    • por exemplo, a 1pode ser empurrada para uma pilha com a 1, 2ou 3no topo, mas a 2só pode ser empurrada para uma pilha com a 2ou 3(ou superior) na parte superior.

    • Isso tem o efeito de que as pilhas sempre aumentam monotonicamente de cima para baixo.

  • Qualquer pilha não vazia pode ser removida e, assumindo que o marcador anterior seja satisfeito, qualquer pilha pode ser enviada para.

  • Qualquer número pode ser colocado em uma pilha vazia.

  • As pilhas não têm limite de altura máximo.

  • Pilhas não podem ser criadas ou destruídas, sempre há N delas.

Esse desafio é decidir o que faz o pop e o push a fim de concluir a troca de stacks, não necessariamente com o menor número de jogadas, mas de uma maneira infalível.

(Praticar com um baralho de cartas é uma boa maneira de entender o problema.)

Desafio

Escreva um programa ou função que receba um número inteiro positivo N, com garantia de 3 ou superior. Imprima ou retorne uma sequência que denota todas as ações de envio rápido necessárias para reorganizar as pilhas a partir do estado inicial:

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 casos)

Para o estado final:

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

Cada linha na sua saída deve conter dois números separados por um espaço. O primeiro número é o índice da pilha para a qual sair e o segundo número é o índice da pilha para a qual empurrar. A execução das ações de todas as linhas em ordem deve organizar as pilhas corretamente, sem violar nenhuma regra.

Por exemplo, aqui está uma saída potencial válida para o caso 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

Notas

  • Sua saída não precisa ser ótima , apenas correta. ou seja, você não precisa minimizar o número de pops e pushs.

    • Por isso, tudo bem se, digamos, alguma ação fosse repetida e imediatamente revertida.
    • Saltar e empurrar para a mesma pilha em um movimento, por exemplo 2 2, também é permitido (embora, obviamente, sem sentido).
  • Sua saída faz necessidade de ser determinista e finito.

  • Lembre-se de que as pilhas têm indexação baseada em 1. A indexação baseada em 0 não é permitida.

  • N maior que 9 deve, obviamente, funcionar tão bem quanto um dígito N.

  • Se desejar, você pode usar dois caracteres ASCII imprimíveis e sem dígito, em vez de espaços e novas linhas. Uma nova linha à direita (ou substituta da nova linha) na saída está correta.

Pontuação

O código mais curto em bytes vence. O desempatador é a resposta votada mais alta.

Brownie sem valor aponta se você pode mostrar que seu algoritmo é ideal.

Passatempos de Calvin
fonte
Pare com o absurdo "pontos extras para pequenas coisas"> _>
user48538
18
@ zyabin101 Você acabou de perder qualquer chance de brownies.
Hobbies de Calvin
9
Você sempre cria títulos maravilhosos!
Luis Mendo
@HelkaHomba-._(._.)_.-
user48538
A saída possível que você inclui para o caso N=3ideal?
R. Kap

Respostas:

9

Pyth 96 94 bytes

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

Experimente aqui

Como funciona?

Esta explicação estará usando N = 5.

Parte 1: Crie a camada inferior em cada pilha

A razão pela qual isso precisa de um trecho de código separado é porque todas as pilhas precisam ser usadas: as 4 primeiras precisam de um 5 para serem colocadas embaixo delas, e a última pilha deve fornecer os 5s. Isso significa que não podemos simplesmente mover todos os 4s para algum lugar, colocar um 5 ali e mover os 4s de volta.

Visualização: (parênteses significam o que será movido)

     _
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

Em vez disso, para fazer essa primeira troca, primeiro moveremos todos os 1s para a segunda pilha, moveremos 5 para a primeira pilha (que agora está vazia), moveremos os 1s para a terceira pilha, moveremos os 2s para a primeira pilha pilha, mova os 1s de volta para a primeira pilha e, finalmente, mova um 5 para a segunda pilha.

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

Agora que temos um espaço livre para mover as pilhas (pilha 2, que contém apenas um 5 colocado no lugar certo), podemos mover todos os 3s para a pilha 2 e colocar 5 na pilha 3. Podemos então repetir a mesma coisa para a pilha 4, e agora temos todos os 5s no lugar certo! E só mais uma coisa: moveremos todos os 1s para a pilha 5, para obter uma boa configuração para a próxima troca de pilhas.

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

Parte 2: Faça todo o resto :)

Isso é muito mais fácil agora, porque agora sempre teremos uma pilha livre para mover outros números que precisamos manipular. Então, primeiro vamos descobrir onde está o 4. Um pouco de exame mostrará que sempre estará 1 acima de onde começou ou 2 acima da última pilha. Agora, continuamos descendo as pilhas, colocando um 4 na pilha, se estiver livre, ou movendo os outros números para cima 1 pilha, se não estiver. Agora temos todos os 4s no lugar.

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

Agora, percebemos que os 3s são 2 pilhas acima de onde os 4s estão. Isso significa que podemos fazer exatamente a mesma coisa que fizemos com os 4s! E, como se vê, podemos continuar fazendo isso, desde que empacotemos o índice da pilha para o outro lado.

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

E assim, podemos continuar fazendo isso até trocarmos todas as pilhas.

Explicação do código:

Primeiro de tudo: As (importantes) variáveis ​​predefinidas.

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

Existem 2 definições de lambda.

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?)

A troca de pilha: parte 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

A troca de pilha: parte 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

Eu já sei que não estou conseguindo pontos brownie, porque eu posso ver muitos métodos mais eficientes e mais complicados :(

K Zhang
fonte