Trao đổi ngăn xếp


23

Vấn đề

Giả sử bạn có N ngăn xếp có tên S 1 đến S N , trong đó mỗi S k (k = 1 đến N) chứa N bản sao của số k.

Ví dụ: khi N = 3, các ngăn xếp trông như thế này:

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

Ở đây có 3 ngăn xếp được lập chỉ mục là 1, 2 và 3 và mỗi ngăn chứa N thể hiện của chỉ mục riêng.

Mục tiêu là sắp xếp lại các ngăn xếp N sao cho mỗi ngăn chứa chúng giống hệt nhau chứa các số từ 1 đến N theo thứ tự từ trên xuống dưới.

ví dụ: với N = 3, mục tiêu là sắp xếp lại các ngăn xếp thành:

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

Hành động duy nhất bạn có thể thực hiện với các ngăn xếp là lấy số cao nhất từ ​​một trong các ngăn xếp (bật lên) sau đó ngay lập tức đặt nó lên trên một ngăn xếp khác (đẩy) . Điều này tuân theo các quy định sau:

  • Một số chỉ có thể được đẩy lên một ngăn xếp nếu nó nhỏ hơn hoặc bằng số trên cùng của ngăn xếp đó.

    • ví dụ: a 1có thể được đẩy lên một ngăn xếp có a 1, 2hoặc 3ở trên cùng, nhưng 2chỉ có thể được đẩy lên một ngăn xếp có một 2hoặc 3(hoặc cao hơn) ở trên cùng.

    • Điều này có tác dụng là các ngăn xếp luôn tăng đơn điệu từ trên xuống dưới.

  • Bất kỳ ngăn xếp không trống nào có thể được bật ra và, giả sử viên đạn trước đó được thỏa mãn, bất kỳ ngăn xếp nào cũng có thể được đẩy tới.

  • Bất kỳ số nào có thể được đẩy vào một ngăn xếp trống.

  • Ngăn xếp không có giới hạn chiều cao tối đa.

  • Ngăn xếp không thể được tạo ra hoặc phá hủy, luôn có N trong số chúng.

Thử thách này là về việc quyết định nên bật và đẩy để làm gì để hoàn thành việc trao đổi ngăn xếp, không nhất thiết là trong một vài động tác, nhưng theo một cách chắc chắn.

(Thực hành với một cỗ bài là một cách tốt để cảm nhận vấn đề.)

Thử thách

Viết chương trình hoặc hàm lấy số nguyên dương N, được đảm bảo là 3 hoặc cao hơn. In hoặc trả về một chuỗi biểu thị tất cả các hành động đẩy pop cần thiết để sắp xếp lại các ngăn xếp từ trạng thái ban đầu:

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 trường hợp)

Đến trạng thái cuối cùng:

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

Mỗi dòng trong đầu ra của bạn phải chứa hai số cách nhau bởi một khoảng trắng. Số đầu tiên là chỉ mục của ngăn xếp bật lên và số thứ hai là chỉ mục của ngăn xếp để đẩy tới. Thực hiện các hành động của tất cả các dòng theo thứ tự nên sắp xếp các ngăn xếp chính xác mà không vi phạm bất kỳ quy tắc nào.

Ví dụ: đây là một đầu ra hợp lệ tiềm năng cho trường hợp 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

Ghi chú

  • Đầu ra của bạn không cần phải tối ưu , chỉ đúng. tức là bạn không cần giảm thiểu số lần bật và đẩy.

    • Vì vậy, sẽ ổn thôi nếu, nói rằng, một số động thái được lặp đi lặp lại và ngay lập tức đảo ngược.
    • Popping và đẩy vào cùng một ngăn xếp trong một lần di chuyển, ví dụ 2 2, cũng được cho phép (mặc dù tất nhiên là vô nghĩa).
  • Đầu ra của bạn không cần phải xác định và hữu hạn.

  • Hãy nhớ rằng ngăn xếp có chỉ mục 1 dựa trên. Lập chỉ mục dựa trên 0 không được phép.

  • N lớn hơn 9 nên tất nhiên chỉ hoạt động tốt như một chữ số N

  • Nếu muốn, bạn có thể sử dụng bất kỳ hai ký tự ASCII có thể in khác nhau, không có chữ số thay cho dấu cách và dòng mới. Một dòng mới (hoặc thay thế dòng mới) trong đầu ra là tốt.

Chấm điểm

Mã ngắn nhất tính bằng byte thắng. Tiebreaker là câu trả lời bình chọn cao hơn.

Điểm brownie vô giá trị nếu bạn có thể hiển thị thuật toán của mình là tối ưu.


Dừng lại với "điểm thêm cho những điều nhỏ nhặt" vô nghĩa> _>
user48538

18
@ zyabin101 Bạn vừa mất bất kỳ cơ hội nào tại brownies.
Sở thích của Calvin

9
Bạn luôn luôn đưa ra những tiêu đề tuyệt vời như vậy!
Luis Mendo

@HelkaHomba-._(._.)_.-
dùng48538

Là đầu ra có thể bạn bao gồm cho trường hợp N=3tối ưu?
R. Kap

Câu trả lời:


9

Pyth 96 94 byte

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

Hãy thử nó ở đây

Làm thế nào nó hoạt động?

Giải thích này sẽ được sử dụng N = 5.

Phần 1: Tạo lớp dưới cùng trên mỗi ngăn xếp

Lý do tại sao điều này cần một đoạn mã riêng là vì mỗi ngăn xếp cần được sử dụng: 4 đầu tiên cần 5 để đặt bên dưới chúng và ngăn xếp cuối cùng phải cung cấp 5s. Điều này có nghĩa là chúng ta không thể di chuyển tất cả các 4s ở đâu đó, đặt 5 ở đó và di chuyển 4s trở lại.

Hình dung: (dấu ngoặc đơn có nghĩa là những gì sẽ được di chuyển)

     _
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

Thay vào đó, để thực hiện trao đổi đầu tiên này, trước tiên chúng ta sẽ chuyển tất cả các số 1 sang ngăn xếp thứ hai, di chuyển 5 đến ngăn xếp thứ nhất (hiện đang trống), di chuyển 1 đến ngăn thứ ba, di chuyển 2 giây sang ngăn thứ nhất ngăn xếp, di chuyển 1s trở lại ngăn xếp đầu tiên và cuối cùng di chuyển 5 đến ngăn xếp thứ hai.

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

Bây giờ chúng ta có một không gian trống để di chuyển các ngăn xếp vào (ngăn xếp 2, chỉ chứa 5 được đặt ở vị trí phù hợp), chúng ta có thể di chuyển tất cả 3 giây sang ngăn xếp 2 và đặt 5 trong ngăn xếp 3. Sau đó chúng ta có thể lặp lại điều tương tự cho stack 4, và bây giờ chúng ta có được tất cả 5s ở đúng vị trí! Và chỉ một điều nữa: chúng tôi sẽ chuyển tất cả 1 giây sang stack 5 để chúng tôi có được một thiết lập đẹp cho trao đổi ngăn xếp tiếp theo.

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

Phần 2: Làm mọi thứ khác :)

Điều này bây giờ dễ dàng hơn nhiều, bởi vì bây giờ chúng ta sẽ luôn có một ngăn xếp miễn phí để di chuyển các số khác mà chúng ta cần phải xoay quanh. Vì vậy, đầu tiên chúng tôi tìm ra vị trí của 4. Một chút kiểm tra sẽ cho thấy rằng nó sẽ luôn luôn là 1 từ nơi nó bắt đầu, hoặc 2 trên ngăn xếp cuối cùng. Bây giờ, chúng ta chỉ cần tiếp tục đi xuống các ngăn xếp, đặt 4 trong ngăn xếp nếu nó miễn phí hoặc di chuyển các số khác lên 1 ngăn xếp nếu không. Bây giờ chúng tôi có tất cả các 4s tại chỗ.

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

Bây giờ, chúng tôi nhận ra rằng 3s là 2 ngăn xếp phía trên nơi 4s ở đâu. Điều này có nghĩa là chúng ta có thể làm chính xác những gì chúng ta đã làm với 4s! Và khi nó bật ra, chúng ta có thể tiếp tục làm điều này miễn là chúng ta bọc chỉ số ngăn xếp sang phía bên kia.

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

Và vì vậy, chúng ta có thể tiếp tục làm điều này cho đến khi chúng ta trao đổi tất cả các ngăn xếp.

Mã giải thích:

Trước hết: Các biến (quan trọng) được xác định trước.

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

Có 2 định nghĩa 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?)

Trao đổi ngăn xếp: phần 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

Trao đổi ngăn xếp: phần 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

Tôi đã biết tôi không nhận được điểm brownie, vì tôi có thể thấy nhiều phương pháp hiệu quả hơn và phức tạp hơn :(

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.