スタック交換


23

問題

あなたはNが持っていると言うスタック Sという名前の1 Sを通じてNそれぞれのS、K(Nへのk = 1)は数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つからトップ番号を取得(ポップ)し、すぐに別のスタックのトップに配置(プッシュ)することです。これはこれらの規定に応じてあります:

  • 数値は、スタックの一番上の数値以下である場合にのみスタックにプッシュできます。

    • 例えば、Aが1でスタックにプッシュすることができ12または3上部に、しかし2唯一でスタックにプッシュすることができ2、または3上部に(またはそれ以上)。

    • これには、スタックが常に単調に上から下に増加するという効果があります。

  • 空でないスタックはポップされ、前の弾丸が満たされたと仮定して、スタックがプッシュされます。

  • 任意の数を空のスタックにプッシュできます。

  • スタックには最大の高さ制限はありません。

  • スタックは作成または破棄できません。常にN個あります。

この課題は、スタック交換を完了するためにどのポップとプッシュを行うかを決定することであり、必ずしも最小限の移動ではなく、確実な方法で行います。

(カードのデッキで練習することは、問題を感じる良い方法です。)

チャレンジ

3以上であることが保証されている正の整数Nを取り込むプログラムまたは関数を作成します。スタックを初期状態から再配置するために必要なすべてのポッププッシュアクションを示す文字列を出力または返します。

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

出力の各行には、スペースで区切られた2つの数字が含まれている必要があります。最初の数値はポップするスタックのインデックスで、2番目の数値はプッシュするスタックのインデックスです。すべての行のアクションを順番に実行すると、ルールを破らずにスタックを正しく配置する必要があります。

たとえば、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

ノート

  • 出力は最適である必要なく、正しいだけです。つまり、ポップとプッシュの数を最小限にする必要はありません。

    • それで、例えば、いくつかの動きが繰り返し行われ、すぐに逆になれば大丈夫でしょう。
    • 同じスタックへの1回の移動でのポップとプッシュ2 2も許可されます(もちろん無意味ですが)。
  • 出力確定的で有限である必要あります。

  • スタックには1ベースのインデックス付けがあることに注意してください。0から始まるインデックスは許可されていません。

  • 9より大きいNはもちろん、1桁のNと同じように機能します。

  • 必要に応じて、スペースと改行の代わりに、数字以外の印刷可能なASCII文字を2つ使用できます。出力の末尾の改行(または改行置換)は問題ありません。

得点

バイト単位の最短コードが優先されます。Tiebreakerは、より高い投票数の回答です。

アルゴリズムが最適であることを示すことができれば、価値のないブラウニーポイント。


「小さなことの余分なポイント」ナンセンスで停止> _>
user48538

18
@ zyabin101あなたはブラウニーでチャンスを失いました。
カルビンの趣味

9
あなたはいつもそのような素晴らしいタイトルを思いつきます!
ルイスメンドー

@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を2番目のスタックに移動し、5を最初のスタック(現在は空)に移動し、1を3番目のスタックに移動し、2を最初に移動しますスタックし、1を最初のスタックに戻し、最後に5を2番目のスタックに移動します。

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

スタックを移動するための空きスペースができたので(スタック2には正しい場所に配置された5のみが含まれます)、3をすべてスタック2に移動し、スタック3に5を配置できます。スタック4についても同じことが言え、今ではすべての5が正しい場所にあります!さらにもう1つ、すべての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

ここで、3が4を超える2スタック上にあることがわかります。これは、4で行ったのとまったく同じことができることを意味します!結局のところ、スタックインデックスを反対側にラップする限り、これを実行し続けることができます。

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.