Sử dụng ngăn xếp thứ ba
Nếu bạn đã đọc tiêu đề, bạn có thể hơi bối rối. Chắc chắn chỉ có hai ngăn xếp trong Brain-Flak? Tuy nhiên tôi đảm bảo với bạn rằng nó tồn tại và nó là một trong những công cụ mạnh nhất nếu không phải là công cụ mạnh nhất trong việc viết và chơi gôn Brain-Flak.
"Ngăn xếp thứ ba" là gì?
Mỗi chương trình Brain-Flak sử dụng ngăn xếp thứ ba theo cách này hay cách khác nhưng phần lớn việc sử dụng diễn ra sau hậu trường và thường rất hữu ích khi đơn giản bỏ qua thực tế là nó tồn tại. Mỗi dấu ngoặc trong chương trình sẽ thêm hoặc xóa một mục khỏi ngăn xếp. Ba trong số các dấu ngoặc nhọn ([<
đều thêm một mục vào ngăn xếp trong khi ba liên hợp của chúng )]>
đều loại bỏ một mục khỏi ngăn xếp. Giá trị của mục trên ngăn xếp là giá trị của phạm vi hiện tại của chương trình và sử dụng nilad sẽ sửa đổi giá trị này theo một số cách nhất định. Dấu ngoặc gần)
có chức năng duy nhất là di chuyển một phần tử từ Ngăn thứ ba sang ngăn xếp hiện tại; một cú đẩy.
Hy vọng điều này đang trở nên rõ ràng với bạn. Ngăn xếp thứ ba là một số loại ngăn xếp ghi nhớ các giá trị trả về của mã đã được thực thi. Chúng ta hãy xem qua một ví dụ về một chương trình đơn giản theo dõi hai ngăn xếp thông thường và Ngăn xếp thứ ba.
Thí dụ
Chúng tôi sẽ đi qua chương trình sau đây. Chương trình này đẩy -3, 1, -2
đến ngăn xếp.
(([()()()])(()))
Chúng tôi bắt đầu với ba dấu ngoặc mở, tất cả đều đẩy số 0 đến ngăn thứ ba.
Ngăn xếp của chúng ta bây giờ trông như thế này, Ngăn xếp thứ ba là bên phải và ngăn xếp hoạt động có một ngăn xếp ^
bên dưới:
0
0
0 0 0
^
(([()()()])(()))
^
Bây giờ chúng tôi có ba ()
nilad. Chúng không làm bất cứ điều gì với hai ngăn xếp thông thường, tuy nhiên chúng thực hiện mỗi lần thêm một vào đầu ngăn xếp thứ ba làm cho các ngăn xếp của chúng ta trông giống như:
3
0
0 0 0
^
(([()()()])(()))
^
Bây giờ chúng ta bắt gặp một ]
như đã nêu trước khi niềng răng chặt loại bỏ một mục khỏi Ngăn xếp thứ ba, nhưng]
có chức năng trừ phần tử mà nó loại bỏ khỏi đầu ngăn xếp. Do đó, ngăn xếp mới của chúng tôi sẽ trông như sau:
-3
0 0 0
^
(([()()()])(()))
^
Điều này thật ý nghĩa; [...]
không phủ định ]
nên trừ đi xuống.
Bây giờ chúng ta phải thực thi a )
. Như bạn có khả năng nhớ lại )
là vị trí trong chương trình nơi các công cụ được đẩy lên ngăn xếp, vì vậy chúng tôi sẽ di chuyển đỉnh của Ngăn thứ ba sang ngăn xếp hiện tại, ngoài ra chúng tôi sẽ thêm -3
phần tử tiếp theo vào ngăn xếp thứ ba.
-3 0 -3
^
(([()()()])(()))
^
Một lần nữa, chúng tôi bắt gặp một trong ba dấu ngoặc nhọn mở của chúng tôi vì vậy chúng tôi sẽ thêm một yếu tố khác vào Ngăn xếp thứ ba của chúng tôi.
0
-3 0 -3
^
(([()()()])(()))
^
Như chúng ta đã nói trước đó ()
sẽ tăng đỉnh của ngăn xếp thứ ba của chúng ta lên một.
1
-3 0 -3
^
(([()()()])(()))
^
Và )
sẽ di chuyển đỉnh của Ngăn thứ ba lên ngăn xếp hoạt động và thêm xuống dưới
1
-3 0 -2
^
(([()()()])(()))
^
Cái cuối cùng )
di chuyển Ngăn xếp thứ ba lên ngăn xếp hoạt động và vì không còn phần tử nào trên Ngăn thứ ba để thêm vào, nên không có gì khác.
-2
1
-3 0
^
(([()()()])(()))
^
Chương trình kết thúc nên chúng tôi chấm dứt và đầu ra.
Ví dụ này nhằm cung cấp cho bạn cảm giác về Thứ ba là gì và làm gì. Nó không bao gồm tất cả các hoạt động, nhưng hy vọng bạn có thể tự mình tìm ra những gì chúng thực hiện. Nếu bạn vẫn đang vật lộn, tôi đã bao gồm một "chiếc áo choàng" ở cuối câu trả lời này để giúp bạn thực hiện.
Ok, vậy thì sao?
Ok, bây giờ bạn đã hiểu Ngăn xếp thứ ba, nhưng "Vậy thì sao"? Bạn đã sử dụng nó ngay cả khi bạn không gọi nó là "Ngăn thứ ba", làm thế nào để suy nghĩ về Ngăn xếp thứ ba giúp bạn chơi golf?
Hãy nhìn vào một vấn đề. Bạn muốn lấy Tam giác của một số . Đây là tổng của tất cả các số nhỏ hơn n.
Một cách tiếp cận có thể là tạo một bộ tích lũy trên offstack và thêm vào nó khi bạn đếm ngược. Điều này tạo ra mã trông như thế này:
(<>)<>{(({}[()])()<>{})<>}{}<>({}<>)
Hãy thử trực tuyến!
Mã này khá nhỏ gọn và người ta có thể nghĩ rằng nó không thể nhỏ hơn nhiều. Tuy nhiên, nếu chúng ta tiếp cận nó từ quan điểm ngăn xếp thứ ba thì rõ ràng điều này rất kém hiệu quả. Thay vì đặt bộ tích lũy của chúng tôi trên offstack, chúng tôi có thể đặt nó vào ngăn xếp thứ ba với một (
và lấy nó ở cuối chúng tôi sử dụng )
. Chúng tôi sẽ một lần nữa lặp lại tất cả các con số, nhưng lần này chúng tôi không phải làm gì nhiều để tăng Thứ ba của chúng tôi, chương trình thực hiện điều đó cho chúng tôi. Điều này trông giống như:
({()({}[()])}{})
Dùng thử trực tuyến
Mã này nhỏ hơn một nửa kích thước của phiên bản golf khá tốt mà chúng tôi đã thực hiện trước đó. Trong thực tế, một tìm kiếm trên máy tính đã chứng minh rằng chương trình này là chương trình ngắn nhất có thể thực hiện được nhiệm vụ này. Chương trình này có thể được giải thích bằng cách sử dụng phương pháp "tổng của tất cả các lần chạy", nhưng tôi nghĩ nó trực quan và rõ ràng hơn rất nhiều khi được giải thích bằng cách sử dụng phương pháp Ngăn xếp thứ ba.
Khi nào tôi sử dụng Ngăn xếp thứ ba?
Lý tưởng nhất là bất cứ khi nào bạn bắt đầu làm việc với một vấn đề mới trong Brain-Flak, bạn nên tự suy nghĩ làm thế nào tôi sẽ làm điều này với Thứ ba trong tâm trí. Tuy nhiên, theo nguyên tắc chung, bất cứ khi nào bạn phải theo dõi một số loại tích lũy hoặc có tổng số hoạt động, bạn nên thử đặt nó lên ngăn xếp thứ ba thay vì hai ngăn xếp thực sự.
Một lần khác có thể là một ý tưởng tốt để xem xét sử dụng ngăn xếp thứ ba của bạn là khi bạn không có bất kỳ không gian nào để lưu trữ một số giá trị trên hai ngăn xếp khác. Điều này có thể đặc biệt hữu ích khi bạn thực hiện các thao tác trên hai ngăn xếp hiện có và bạn muốn lưu một giá trị để sử dụng sau này mà không phải theo dõi vị trí của nó.
Hạn chế của ngăn xếp thứ ba
Ngăn xếp thứ ba rất mạnh theo nhiều cách nhưng nó đi kèm với những hạn chế và nhược điểm riêng.
Thứ nhất, chiều cao ngăn xếp tối đa cho Ngăn xếp thứ ba tại bất kỳ điểm nào được xác định tại thời điểm biên dịch. Điều này có nghĩa là nếu bạn muốn sử dụng một lượng không gian trên ngăn xếp, bạn phải phân bổ không gian đó khi bạn đang viết chương trình.
Thứ hai, ngăn xếp thứ ba không phải là truy cập ngẫu nhiên. Điều này có nghĩa là bạn không thể thực hiện bất kỳ thao tác nào trên bất kỳ giá trị nào ngoài giá trị cao nhất. Ngoài ra, bạn không thể di chuyển các giá trị xung quanh trên ngăn xếp (giả sử trao đổi hai phần tử đầu tiên).
Phần kết luận
Ngăn xếp thứ ba là một công cụ mạnh mẽ và tôi sẽ coi nó là thiết yếu cho mọi người dùng Brain-Flak. Nó cần một số quen thuộc và đòi hỏi một sự thay đổi trong cách suy nghĩ của bạn về lập trình trong Brain-Flak, nhưng khi được sử dụng đúng cách, nó sẽ tạo ra sự khác biệt giữa một phong nha và tuyệt vời khi chơi golf.
Áo choàng
Dưới đây là danh sách các hoạt động và cách chúng ảnh hưởng đến Ngăn xếp thứ ba
Operation | Action
====================================================
(,[,< | Put a zero on top of the Third Stack
----------------------------------------------------
) | Add the top of the Third Stack to the
| second element and move it to the
| active stack
----------------------------------------------------
] | Subtract the top of the Third Stack
| from the second element and pop it
----------------------------------------------------
> | Pop the top of the Third Stack
----------------------------------------------------
() | Add one to the top of the Third Stack
----------------------------------------------------
{} | Pop the top of the active stack and
| add it to the top of the Third Stack
----------------------------------------------------
[] | Add the stack height to the Third
| Stack
----------------------------------------------------
<>,{,} | Nothing