Scambio di stack


23

Problema

Supponi di avere N pile da S 1 a S N , dove ogni S k (k = 1 a N) contiene N copie del numero k.

Ad esempio, quando N = 3 le pile si presentano così:

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

Qui ci sono 3 stack indicizzati come 1, 2 e 3 e ognuno contiene N istanze del proprio indice.

L'obiettivo è riorganizzare le pile N in modo tale che ognuna di esse contenga identicamente i numeri da 1 a N in ordine dall'alto verso il basso.

ad es. per N = 3 l'obiettivo è riordinare le pile in:

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

L'unica azione che puoi eseguire con le pile è prendere il numero più alto da una delle pile (saltar fuori) e posizionarlo immediatamente sopra una pila diversa (spingere) . Questo è soggetto a queste disposizioni:

  • Un numero può essere inserito in una pila solo se è inferiore o uguale al numero in cima a quella pila.

    • ad es. a 1può essere inserito in una pila con a 1, 2o 3nella parte superiore, ma a 2può essere inserito in una pila con una 2o 3(o superiore) nella parte superiore.

    • Ciò ha l'effetto che le pile aumentano sempre monotonicamente dall'alto verso il basso.

  • Qualsiasi pila non vuota può essere espulsa e, supponendo che il proiettile precedente sia soddisfatto, qualsiasi pila può essere spinta verso.

  • Qualsiasi numero può essere inserito in una pila vuota.

  • Le pile non hanno limiti di altezza massima.

  • Le pile non possono essere create o distrutte, ce ne sono sempre N.

Questa sfida consiste nel decidere quali pop e push fare per completare lo scambio di stack, non necessariamente con il minor numero di mosse, ma in modo sicuro.

(Fare pratica con un mazzo di carte è un buon modo per farsi un'idea del problema.)

Sfida

Scrivi un programma o una funzione che accetta un numero intero positivo N, garantito che sia 3 o superiore. Stampa o restituisci una stringa che denota tutte le azioni pop-push richieste per riorganizzare le pile dallo stato iniziale:

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

Allo stato finale:

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

Ogni riga nell'output deve contenere due numeri separati da uno spazio. Il primo numero è l'indice dello stack da cui eseguire il pop-up e il secondo numero è l'indice dello stack da spingere. L'esecuzione delle azioni di tutte le linee in ordine dovrebbe disporre correttamente le pile senza infrangere alcuna regola.

Ad esempio, ecco un potenziale output valido per il 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

Gli appunti

  • Non è necessario che l' output sia ottimale , ma solo corretto. cioè non è necessario minimizzare il numero di pop e push.

    • Quindi andrebbe bene se, diciamo, qualche mossa fosse ripetutamente fatta e immediatamente invertita.
    • Popping e spingere allo stesso stack in una mossa, ad esempio 2 2, è anche permesso (anche se ovviamente inutile).
  • L'output non necessità di essere deterministico e finito.

  • Ricorda che gli stack hanno l'indicizzazione basata su 1. L'indicizzazione basata su 0 non è consentita.

  • Ovviamente N maggiore di 9 dovrebbe funzionare allo stesso modo di una singola cifra N.

  • Se lo si desidera, è possibile utilizzare due caratteri ASCII stampabili non digitabili al posto di spazi e nuove righe. Una nuova riga finale (o sostituto nuova riga) nell'output va bene.

punteggio

Vince il codice più breve in byte. Tiebreaker è la risposta più votata.

Punti brownie senza valore se puoi mostrare che il tuo algoritmo è ottimale.


Basta con l'assurdità dei "punti extra per le piccole cose"> _>
user48538

18
@ zyabin101 Hai appena perso qualsiasi possibilità ai brownies.
Calvin's Hobbies,

9
Ti vengono sempre in mente titoli così meravigliosi!
Luis Mendo,

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

Il possibile output che includi per il caso di N=3ottimale?
R. Kap

Risposte:


9

Pyth 96 94 byte

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

Provalo qui

Come funziona?

Questa spiegazione utilizzerà N = 5.

Parte 1: crea il livello inferiore su ogni pila

Il motivo per cui è necessario un codice separato è perché ogni stack deve essere utilizzato: i primi 4 hanno bisogno di un 5 da mettere sotto di loro e l'ultimo stack deve fornire i 5. Ciò significa che non possiamo semplicemente spostare tutti i 4 da qualche parte, mettere un 5 lì e spostare i 4 indietro.

Visualizzazione: (le parentesi indicano cosa verrà spostato)

     _
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

Invece, per fare questo primo scambio, per prima cosa sposteremo tutti gli 1 sul secondo stack, sposteremo un 5 sul primo stack (che ora è vuoto), spostiamo gli 1 sul terzo stack, spostiamo i 2 sul primo stack, sposta gli 1 di nuovo sul primo stack e infine sposta un 5 sul secondo stack.

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

Ora che abbiamo uno spazio libero in cui spostare gli stack (stack 2, che contiene solo un 5 che è posizionato nel punto giusto), possiamo spostare tutti i 3 nello stack 2 e posizionare un 5 nello stack 3. Possiamo quindi ripetere la stessa cosa per lo stack 4, e ora abbiamo tutti i 5 nel posto giusto! E solo un'altra cosa: sposteremo tutti gli 1 nello stack 5 in modo da ottenere una buona configurazione per il prossimo scambio di stack.

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

Parte 2: fai tutto il resto :)

Ora è molto più facile, perché ora avremo sempre uno stack gratuito per spostare altri numeri in cui dobbiamo destreggiarci. Quindi, prima scopriamo dove si trova il 4. Un po 'di esame mostrerà che sarà sempre 1 in su da dove è iniziato, o 2 sopra l'ultimo stack. Ora, continuiamo a scendere le pile, posizionando un 4 nello stack se è gratuito o spostando gli altri numeri in alto di 1 stack se non lo è. Ora abbiamo tutti i 4 in atto.

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

Ora, ci rendiamo conto che i 3 sono 2 pile sopra dove i 4 dove. Ciò significa che possiamo fare esattamente la stessa cosa che abbiamo fatto con i 4! E a quanto pare, possiamo continuare a farlo fintanto che avvolgiamo l'indice dello stack dall'altra parte.

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

E così, possiamo continuare a farlo fino a quando non abbiamo scambiato tutte le pile.

Spiegazione del codice:

Prima di tutto: le (importanti) variabili predefinite.

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

Ci sono 2 definizioni 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?)

Lo scambio di stack: 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

Scambio di stack: 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

So già che non ottengo punti brownie, perché posso vedere molti metodi più efficienti e più complicati :(

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.