Intercambio de pilas


23

Problema

Supongamos que tiene N pilas llamadas S 1 a S N , donde cada S k (k = 1 a N) contiene N copias del número k.

Por ejemplo, cuando N = 3 las pilas se ven así:

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

Aquí hay 3 pilas indexadas como 1, 2 y 3, y cada una contiene N instancias de su propio índice.

El objetivo es reorganizar las N pilas de modo que cada una de ellas contenga idénticamente los números del 1 al N en orden de arriba a abajo.

Por ejemplo, para N = 3, el objetivo es reorganizar las pilas en:

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

La única acción que puede realizar con las pilas es tomar el número superior de una de las pilas (estallar) e inmediatamente colocarlo encima de una pila diferente (empujar) . Esto está sujeto a estas estipulaciones:

  • Un número solo se puede insertar en una pila si es menor o igual que el número superior en esa pila.

    • por ejemplo, a 1se puede empujar a una pila con a 1, 2o 3en la parte superior, pero a 2solo se puede empujar a una pila con a 2o 3(o más alto) en la parte superior.

    • Esto tiene el efecto de que las pilas siempre están aumentando monotónicamente de arriba a abajo.

  • Se puede extraer cualquier pila no vacía y, suponiendo que se satisfaga la viñeta anterior, se puede empujar a cualquier pila.

  • Cualquier número puede ser empujado a una pila vacía.

  • Las pilas no tienen límite de altura máxima.

  • Las pilas no se pueden crear ni destruir, siempre hay N de ellas.

Este desafío se trata de decidir qué pops y empujes hacer para completar el intercambio de stack, no necesariamente en la menor cantidad de movimientos, sino de una manera segura.

(Practicar con una baraja de cartas es una buena manera de tener una idea del problema).

Reto

Escriba un programa o función que tome un entero positivo N, garantizado como 3 o superior. Imprima o devuelva una cadena que denote todas las acciones de empuje emergente necesarias para reorganizar las pilas desde el 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 caso)

Al 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 línea en su salida debe contener dos números separados por un espacio. El primer número es el índice de la pila a partir de la cual saltar y el segundo número es el índice de la pila a empujar. Realizar las acciones de todas las líneas en orden debe organizar las pilas correctamente sin romper ninguna regla.

Por ejemplo, aquí hay una salida válida potencial para el 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

  • Su salida no necesita ser óptima , solo correcta. es decir, no necesita minimizar la cantidad de pops y empujones.

    • Por lo tanto, estaría bien si, por ejemplo, se hiciera algún movimiento repetidamente y se invirtiera de inmediato.
    • Hacer estallar y empujar a la misma pila en un solo movimiento, por ejemplo 2 2, también está permitido (aunque, por supuesto, no tiene sentido).
  • Su salida hace necesidad de ser determinista y finito.

  • Recuerde que las pilas tienen indexación basada en 1. La indexación basada en 0 no está permitida.

  • N mayor que 9, por supuesto, debería funcionar tan bien como un solo dígito N.

  • Si lo desea, puede usar dos caracteres ASCII imprimibles distintos que no sean dígitos en lugar de espacios y líneas nuevas. Una nueva línea final (o un sustituto de nueva línea) en la salida está bien.

Tanteo

El código más corto en bytes gana. Tiebreaker es la respuesta más votada.

Puntos brownie sin valor si puede mostrar que su algoritmo es óptimo.


Parada con los "puntos extra para las cosas pequeñas" sin sentido> _>
user48538

18
@ zyabin101 Acabas de perder la oportunidad de comer brownies.
Calvin's Hobbies

99
¡Siempre se te ocurren títulos tan maravillosos!
Luis Mendo

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

¿El resultado posible que incluye para el caso es N=3óptimo?
R. Kap

Respuestas:


9

Pyth 96 94 bytes

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

Pruébalo aquí

¿Como funciona?

Esta explicación usará N = 5.

Parte 1: crea la capa inferior en cada pila

La razón por la que esto necesita un código separado es porque cada pila necesita ser utilizada: los primeros 4 necesitan que se coloque un 5 debajo de ellos, y la última pila debe proporcionar los 5. Esto significa que no podemos mover todos los 4 en algún lugar, poner un 5 allí y mover los 4 hacia atrás.

Visualización: (los paréntesis significan lo que se moverá)

     _
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

En cambio, para hacer este primer intercambio, primero vamos a mover todos los 1s a la segunda pila, mover un 5 a la primera pila (que ahora está vacía), mover los 1s a la tercera pila, mover los 2s a la primera apilar, mover los 1s a la primera pila y finalmente mover un 5 a la segunda pila.

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

Ahora que tenemos un espacio libre para mover las pilas (pila 2, que solo contiene un 5 que se coloca en el lugar correcto), podemos mover todos los 3 a la pila 2 y colocar un 5 en la pila 3. Luego podemos repetir ¡Lo mismo para la pila 4, y ahora tenemos todos los 5 en el lugar correcto! Y solo una cosa más: moveremos todos los 1s al stack 5 para que tengamos una buena configuración para el próximo intercambio de stack.

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

Parte 2: Haz todo lo demás :)

Esto es mucho más fácil ahora, porque ahora siempre tendremos una pila libre para mover otros números con los que debemos hacer malabarismos. Entonces, primero descubrimos dónde está el 4. Un poco de examen mostrará que siempre estará 1 arriba de donde comenzó, o 2 arriba de la última pila. Ahora, seguimos bajando por las pilas, colocando un 4 en la pila si está libre, o subiendo los otros números 1 pila si no lo está. Ahora tenemos todos los 4 en su lugar.

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

Ahora, nos damos cuenta de que los 3 son 2 pilas por encima de donde están los 4. ¡Esto significa que podemos hacer exactamente lo mismo que hicimos con los 4s! Y resulta que podemos seguir haciéndolo siempre que envuelvamos el índice de la pila al otro lado.

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

Y así, podemos seguir haciendo esto hasta que hayamos intercambiado todas las pilas.

Explicación del código:

En primer lugar: las variables (importantes) predefinidas.

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

Hay 2 definiciones 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?)

El intercambio de la pila: 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

El intercambio de la pila: 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

Ya sé que no estoy obteniendo puntos de brownie, porque puedo ver muchos métodos más eficientes y más complicados :(

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.