<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Đầu vào được N
theo sau bởi chuỗi, được phân tách bằng bất kỳ ký tự không phải là số.
Hãy thử trực tuyến!
Điều này được viết với sự hợp tác của Sp3000 (có nghĩa là tôi không thể bận tâm tìm ra thuật toán, vì vậy anh ấy bắt đầu làm việc với nó, đưa ra giải pháp 118 byte nhưng không thể chơi golf được, vì vậy tôi đã chơi golf. .. yay cho tinh thần đồng đội).
Giải trình
Sơn lót thông thường của Sp (như thường được sửa đổi một chút):
- Labyrinth là một ngôn ngữ 2D dựa trên ngăn xếp với hai ngăn xếp, chính và phụ. Khá nhiều thứ xảy ra trên ngăn xếp chính, nhưng bạn có thể chuyển các giá trị sang ngăn khác, ví dụ để đảo ngược chúng hoặc lưu chúng cho lần sau.
- Các ngăn xếp là không đáy và chứa đầy số không, vì vậy xuất hiện từ một ngăn xếp trống không phải là một lỗi.
- Thực thi bắt đầu từ ký tự hợp lệ đầu tiên (ở đây trên cùng bên trái). Tại mỗi ngã ba, nơi có hai hoặc nhiều đường dẫn có thể cho con trỏ lệnh (IP) đi, đỉnh của ngăn xếp được kiểm tra để xác định nơi tiếp theo. Tiêu cực là rẽ trái, không là đi tiếp và tích cực là rẽ phải. Mặc dù điều này có nghĩa là làm cho mã trông giống như những đoạn quanh co, khúc khuỷu, nhưng không có gì ngăn bạn làm "phòng" nơi những điều kiện này được kiểm tra trong mỗi ô. Những người có thể mang lại hành vi khá khó lường, nhưng là tuyệt vời cho chơi golf.
- Mã nguồn (và do đó bố cục của mê cung) có thể được sửa đổi trong thời gian chạy bằng cách sử dụng
<>^v
theo chu kỳ một hàng hoặc cột hoặc lưới.
"
là không-ops.
Ở đây chúng tôi đi.
Mã bắt đầu trên <
, đó là một mẹo chơi gôn mà tôi đã sử dụng một vài lần khi bắt đầu với một đoạn mã tuyến tính dài. Nó dịch chuyển hàng đầu tiên theo chu kỳ sang trái, với IP trên đó , vì vậy nguồn sẽ trông như thế này:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Nhưng bây giờ IP không thể di chuyển bất cứ nơi nào, vì vậy nó thực hiện <
lại. Điều này tiếp tục cho đến khi chúng ta đạt đến trạng thái này:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Tại thời điểm này, IP có thể rời khỏi ô và bắt đầu thực hiện dòng thứ hai bắt đầu từ ?
. Vì vậy, đây là mã tuyến tính được chia nhỏ:
? # Read the first integer on STDIN, i.e. N.
:} # Duplicate it and move one copy over to the auxiliary stack.
, # Read the separator character.
,. # Read the first character of the input string and directly print it.
IP bây giờ đi vào phòng 3x2 này, thực sự là hai vòng lặp 2x2 được nén chặt (chồng chéo) theo chiều kim đồng hồ. Vòng lặp đầu tiên đọc và loại bỏ các N-1
ký tự khỏi STDIN.
; # Discard the top of the stack. On the first iteration, this is the
# separator we've already read. On subsequent iterations this will be
# one of the N-1 characters from the input string.
( # Decrement N. If this hits zero, we leave the loop, otherwise we continue.
, # Read the next character from STDIN to be discarded.
Bây giờ chúng ta nhập vòng lặp thứ hai đọc phần còn lại của chuỗi đầu vào. Chúng tôi có thể phát hiện EOF vì ,
sẽ quay trở lại -1
trong trường hợp đó, làm cho IP rẽ trái.
, # Read a character. Exit the loop if EOF.
( # Decrement it.
Sự giảm giá đó không thực sự hữu ích, nhưng chúng ta có thể hoàn tác miễn phí sau đó và ở đây nó cho phép chúng ta chồng chéo hai vòng.
Nếu chúng ta lấy 5 ABCDEFGHIJKLMNOP
đầu vào làm ví dụ, ngăn xếp trông như thế này:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' -1 | 5 ... ] Auxiliary
Lưu ý rằng những cái này thực sự tương ứng với các ký tự đầu vào FGHIJKLMNOP
(vì chúng tôi đã giảm chúng) và chúng tôi thực sự không muốn in những ký tự đầu tiên (chúng tôi chỉ loại bỏ các N-1
ký tự, nhưng muốn bỏ qua N
).
Bây giờ có một bit tuyến tính ngắn chuẩn bị ngăn xếp cho vòng lặp tiếp theo:
; # Discard the -1.
= # Swap the tops of the stacks, i.e. N with the last character.
# By putting the last character on the auxiliary stack, we ensure that
# it doesn't get discarded in the next loop.
} # Move N over to the auxiliary stack as well.
Các ngăn xếp bây giờ trông giống như:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' | 5 'O' ... ] Auxiliary
Chúng tôi nhập một vòng lặp 2x2 theo chiều kim đồng hồ. Điều này loại bỏ các N
ký tự hàng đầu từ ngăn xếp chính:
; # Discard the top of the main stack.
{ # Pull N over from the auxiliary stack.
( # Decrement it. It it's 0 we leave the loop.
} # Push N back to the auxiliary stack.
Khi chúng ta thoát khỏi vòng lặp =
hoán đổi đó 0
và ký tự cuối cùng của chuỗi đầu vào một lần nữa. Bây giờ các ngăn xếp trông như thế này:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'O' | ... ] Auxiliary
Chúng tôi muốn in nội dung của ngăn xếp chính (ngoại trừ phần tử dưới cùng và tất cả tăng thêm 1), từ bên trái . Điều đó có nghĩa là chúng ta cần đưa nó vào ngăn xếp phụ trợ. Đó là những gì vòng lặp 2x2 (theo chiều kim đồng hồ) tiếp theo làm:
{ # Pull an element over from the auxiliary stack. This is necessary so we
# have a 0 on top of the stack when entering the loop, to prevent the IP
# from turning right immediately.
} # Move the top of the main stack back to the auxiliary stack. If this was the
# bottom of the stack, exit the loop.
) # Increment the current character.
} # Move it over to the auxiliary stack.
Ngăn xếp ngay bây giờ:
Main [ ... | 'F' 'G' 'H' 'I' 'J' 'P] ... ] Auxiliary
Chúng tôi di chuyển cái đầu tiên (cái mà chúng tôi không muốn in) trở lại ngăn xếp chính với {
. Và bây giờ chúng ta nhập vòng lặp 2x2 ( ngược chiều kim đồng hồ ) cuối cùng , in phần còn lại:
{ # Pull another character over from the auxiliary stack. Exit the loop
# if that's the zero at the bottom of the stack.
. # Print the character.
Cuối cùng chúng tôi chấm dứt chương trình với @
.
'
như ký tự đếm? Ví dụ :''123321
?