Fueue , 423 byte
Fueue là một esolang dựa trên hàng đợi trong đó chương trình đang chạy là hàng đợi.
)$$4255%%1(~):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]](H-):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Hãy thử trực tuyến!
Làm thế nào nó hoạt động
Giải thích này có thể có hoặc không có cách nào ra khỏi tầm tay. Mặt khác, tôi không biết làm thế nào để giải thích nó ngắn hơn nhiều theo cách tôi hy vọng mọi người có thể làm theo.
Bảng cheat Fueue
Xem bài viết wiki esolang để biết chi tiết, bao gồm một số tính năng không được sử dụng trong chương trình này.
Chương trình ban đầu là trạng thái ban đầu của hàng đợi, có thể chứa các thành phần sau:
- Các chữ nguyên (chỉ không âm trong nguồn, nhưng có thể tính toán âm), thực hiện chúng in một ký tự.
- Các khối lồng nhau được phân tách bằng khung vuông, trơ (được bảo toàn nguyên vẹn trừ khi một số chức năng tác động lên chúng).
- Các hàm, đối số của chúng là các phần tử theo sau chúng ngay lập tức trong hàng đợi:
+*/-%
: số học số nguyên ( -
là đơn nguyên, %
phủ định logic). Trơ nếu không đưa ra đối số số.
()<
: đặt phần tử trong ngoặc, xóa dấu ngoặc khỏi khối, thêm phần tử cuối cùng vào khối. Hai cái sau trơ trừ khi theo sau là một khối.
~:
: hoán đổi, nhân đôi.
$
: sao chép (lấy số + phần tử). Trơ trước không số.
H
: tạm dừng chương trình.
Lưu ý rằng trong khi []
lồng, ()
không - cái sau đơn giản là các hàm riêng biệt.
Cú pháp theo dõi thực hiện
Khoảng trắng là tùy chọn trong Fueue, ngoại trừ giữa các chữ số. Trong các dấu vết thực hiện sau đây, nó sẽ được sử dụng để đề xuất cấu trúc chương trình, cụ thể:
- Khi một hàm thực thi, nó và các đối số của nó sẽ được đặt ra từ các phần tử xung quanh có khoảng trắng. Nếu một số đối số phức tạp, có thể có một khoảng cách giữa chúng.
- Nhiều dấu vết thực hiện được chia thành một "blob delay" ở bên trái, được tách từ một phần bên phải để thực hiện thao tác dữ liệu đáng kể. Xem phần tiếp theo.
Dấu ngoặc nhọn {}
(không được sử dụng trong Fueue) được sử dụng trong các dấu vết để biểu thị kết quả số nguyên của các biểu thức toán học. Điều này bao gồm các số âm, vì Fueue chỉ có nghĩa đen không âm - -
là hàm phủ định.
Tên biến đổi khác nhau và ...
được sử dụng để biểu thị các giá trị và chữ viết tắt.
Chiến thuật trì hoãn
Theo trực giác, các chu kỳ thực hiện xung quanh hàng đợi, sửa đổi một phần những gì nó đi qua. Kết quả của một chức năng không thể được thực hiện lại cho đến chu kỳ tiếp theo. Các phần khác nhau của chương trình phát triển song song một cách hiệu quả miễn là chúng không tương tác.
Kết quả là, rất nhiều mã được dành cho đồng bộ hóa, đặc biệt là trì hoãn việc thực hiện các phần của chương trình cho đến thời điểm thích hợp. Có rất nhiều lựa chọn để chơi golf này, có xu hướng biến những phần đó thành những đốm màu không thể đọc được mà chỉ có thể hiểu được bằng cách truy tìm chu kỳ thực hiện của chúng theo chu kỳ.
Những chiến thuật này sẽ không luôn được đề cập riêng trong phần dưới đây:
)[A]
sự chậm trễ A
cho một chu kỳ. (Có lẽ là phương pháp dễ nhất và dễ đọc nhất.)
~ef
hoán đổi các yếu tố e
và f
cũng trì hoãn việc thực hiện của chúng. (Có lẽ là ít đọc nhất, nhưng thường ngắn nhất cho sự chậm trễ nhỏ.)
$1e
trì hoãn một yếu tố duy nhất e
.
-
và %
rất hữu ích cho việc trì hoãn các số (cái sau cho 0
và 1
.)
- Khi trì hoãn một số phần tử bằng nhau trong một hàng
:
hoặc $
có thể được sử dụng để tạo chúng từ một phần tử duy nhất.
(n
kết thúc n
trong ngoặc, mà sau này có thể được gỡ bỏ một cách thuận tiện. Điều này đặc biệt quan trọng đối với các phép tính số, vì các số quá không ổn định thậm chí không được sao chép mà không đặt chúng vào một khối.
Cấu trúc tổng thể
Phần còn lại của lời giải thích được chia thành bảy phần, mỗi phần cho một phần của chương trình đang chạy. Các chu kỳ lớn hơn mà sau đó hầu hết chúng lặp lại sẽ được gọi là "lặp" để phân biệt chúng với "chu kỳ" của các lần đi qua toàn bộ hàng đợi.
Đây là cách chương trình ban đầu được phân chia giữa chúng:
A: )$$4255%%1(~
B: ):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
C:
D: (H-
E:
F:
G: ):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Chữ số lớn ở cuối chương trình mã hóa phần còn lại theo chiều ngược lại, hai chữ số cho mỗi ký tự, trừ 30 từ mỗi giá trị ASCII (ví dụ: 10
mã hóa a (
.)
Ở cấp độ cao hơn, bạn có thể nghĩ về dữ liệu trong chương trình này (bắt đầu bằng bignum) như chảy từ phải sang trái, nhưng điều khiển chảy từ trái sang phải. Tuy nhiên, ở cấp độ thấp hơn, Fueue làm rối loạn sự khác biệt giữa mã và dữ liệu mọi lúc.
- Phần G giải mã bignum thành các chữ số ASCII (ví dụ chữ số
0
là số nguyên 48
), trước tiên tách ra các chữ số có nghĩa ít nhất. Nó tạo ra một chữ số cứ sau 15 chu kỳ.
- Phần F chứa các giá trị ASCII chữ số được sản xuất (mỗi bên trong một khối) cho đến khi phần E có thể tiêu thụ chúng.
- Phần E xử lý hai chữ số được sản xuất cùng một lúc, ghép chúng thành các khối của biểu mẫu
[x[y]]
, cũng in ký tự được mã hóa của mỗi cặp.
- Phần D bao gồm một khối được lồng sâu dần dần được xây dựng từ các
[x[y]]
khối theo cách mà một khi nó chứa tất cả các chữ số, nó có thể được chạy để in tất cả chúng, sau đó tạm dừng toàn bộ chương trình.
- Phần C xử lý việc xây dựng phần D, và cũng tái tạo phần E.
- Phần B tái tạo lại phần C cũng như chính nó sau mỗi 30 chu kỳ.
- Phần A đếm ngược chu kỳ cho đến lần lặp cuối cùng của các phần khác. Sau đó, nó hủy bỏ phần B và chạy phần D.
Mục A
Phần A xử lý lập lịch kết thúc chương trình. Phải mất 4258 chu kỳ để giảm xuống một chức năng hoán đổi duy nhất ~
, sau đó thực hiện điều chỉnh cho phần B dừng vòng lặp chính của nó và bắt đầu chạy phần D thay thế.
)$ $4255% %1 (~
)$%%%...%% %0 [~]
)$%%%...% %1 [~]
⋮
)$ %0 [~]
) $1[~]
)[~]
~
- Một
$
hàm tạo ra 4255 bản sao sau đây %
trong khi (
kết thúc các ~
dấu ngoặc.
- Mỗi chu kỳ cuối cùng
%
được sử dụng để chuyển đổi số sau giữa 0
và 1
.
- Khi tất cả các
%
s được sử dụng hết, $1
tạo 1 bản sao của [~]
(có hiệu quả là NOP) và trong chu kỳ tiếp theo, )
loại bỏ dấu ngoặc.
Mục B
Phần B xử lý việc tự tái tạo cũng như lặp lại mới của phần C cứ sau 30 chu kỳ.
) : [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] [BkB]
)$ $24% %0 :< [~:)~)] ~ [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] [BkB]
)$ %...%%% %1 < < [~:)~)] [BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...%% %0 < [~:)~)[BkB]] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...% %1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
⋮
) $1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
~:) ~)[BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
) : [BkB] ) [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] (2)
) [BkB] [BkB] $11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<
- Một
:
bản sao khối lớn theo sau (một bản sao được viết tắt là [BkB]
), sau đó )
xóa dấu ngoặc khỏi bản sao đầu tiên.
$$24%%0
thiết lập một bộ đếm ngược tương tự như trong phần A.
- Trong khi điều này đếm ngược,
:<
biến thành <<
và ~
hoán đổi hai trong số các khối, đặt mã cho phần C mới.
- Hai
<
hàm đóng gói hai khối cuối cùng vào khối đầu tiên - điều này là không cần thiết trong các lần lặp thông thường, nhưng sẽ cho phép ~
phần A thực hiện công việc của nó ở cuối.
- (1) Khi đếm ngược kết thúc,
)
loại bỏ các dấu ngoặc ngoài. Tiếp theo ~:)
biến thành ):
và ~)
hoán đổi a )
đến đầu mã C.
- (2) Phần B hiện đang quay trở lại chu kỳ ban đầu của nó, trong khi phần A
)
sắp xóa dấu ngoặc để bắt đầu chạy một bước lặp mới của phần C.
Trong lần lặp lại cuối cùng, ~
từ phần A xuất hiện tại điểm (1) ở trên:
~ ) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
[~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] )
Việc ~
hoán đổi )
trên toàn khối và vào phần C, ngăn không cho phần B được chạy lại.
Mục C
Phần C xử lý hợp nhất các cặp ký tự chữ số mới vào khối của phần D và cũng tạo ra các lần lặp mới của phần E.
Dưới đây cho thấy một lần lặp điển hình với x
và y
đại diện cho mã ASCII của các chữ số. Trong lần lặp đầu tiên, các phần tử "D" và "E" đến là ban đầu [H]
và -
thay vào đó, vì không có phần E nào trước đó đã chạy để tạo ra bất kỳ cặp ký tự chữ số nào.
C D E
$11~ ) ~<[[+$4--498+*-:~-10)):])<~] [)))~] < [)))~[...]] [x[y]]
~~~ ~~~ ~~~ ~~) [[+$4--498+*-:~-10)):])<~] < [)))~] [)))~[...][x[y]]]
~~~ ~~~ ) ~ [[+$4--498+*-:~-10)):])<~] [)))~[)))~[...][x[y]]]]
~~~ ~ ) [)))~[....]] [[+$4--498+*-:~-10)):])<~]
~~[)))~[....]] )[[+$4--498+*-:~-10)):])<~]
[)))~[....]] ~[+$4--498+*-:~-10)):])<~
- Điều này sử dụng một phương pháp đồng bộ hóa khác mà tôi phát hiện ra cho câu trả lời này. Khi bạn có một số chức năng hoán đổi
~
liên tiếp, hàng sẽ co lại khoảng 2/3 mỗi chu kỳ (vì một lần ~
hoán đổi hai lần sau), nhưng đôi khi với một phần còn lại ~
sẽ tàn phá những thao tác cẩn thận.
$11~
sản xuất một hàng như vậy. Tiếp theo ~
hoán đổi một <
khối trên khối sau. Một cái khác <
ở cuối sẽ nối một khối cặp chữ số mới (chữ số x và y dưới dạng mã ASCII) vào khối D của phần.
- Chu kỳ tiếp theo,
~
hàng có ~~
phần còn lại, trong đó hoán đổi một ~
phần sau )
. Phần khác <
nối phần D vào một [)))~]
khối.
- Tiếp theo, hoán đổi
~
chính nó hoán đổi khối sau với mã E phần mới trên khối D phần. Sau đó, một phần còn lại mới ~
hoán đổi một đường )
ngang, và cuối cùng, hàng cuối cùng ~~
trong ~
hàng đổi một trong số chúng sang phần E giống như )
đã loại bỏ dấu ngoặc của nó.
Trong lần lặp lại cuối cùng, phần A ~
đã hoán đổi một )
phần B và sang phần C. Tuy nhiên, phần C ngắn ngủi đến nỗi nó đã biến mất, và )
kết thúc ở đầu phần D.
Mục D
Phần D xử lý in số lớn cuối cùng và tạm dừng chương trình. Trong phần lớn thời gian chạy chương trình, đó là một khối trơ mà các phần B thẩm G hợp tác xây dựng.
(H -
[H]-
⋮
[)))~[H-]] After one iteration of section C
⋮
[)))~[)))~[H-][49[49]]]] Second iteration, after E has also run
⋮
) [)))~[...]] [49[48]] Final printing starts as ) is swapped in
))) ~[...][49[48]]
)) )[49[48]] [...]
)) 49 [48][...] Print first 1
) )[48] [...]
) 48 [...] Print 0
)[...] Recurse to inner block
...
⋮
)[H-] Innermost block reached
H - Program halts
- Trong chu kỳ đầu tiên của chương trình, hàm
(
kết thúc chức năng tạm dừng H
trong ngoặc. Sau -
đây, nó sẽ được sử dụng như một phần tử giả cho lần lặp đầu tiên thay vì một cặp chữ số.
- Cặp chữ số thực đầu tiên được kết hợp là
[49[49]]
, tương ứng với số cuối cùng 11
trong chữ số.
- Cặp chữ số cuối cùng
[49[48]]
(tương ứng với phần 10
đầu của chữ số) không thực sự được tích hợp vào khối, nhưng điều này không tạo ra sự khác biệt nào )[A[B]]
và )[A][B]
tương đương, cả hai đều biến thành A[B]
.
Sau lần lặp cuối cùng, phần )
hoán đổi ngay từ phần B đến và khối D được gỡ rối. Ở )))~
đầu mỗi khối phụ đảm bảo rằng tất cả các phần được thực hiện theo đúng thứ tự. Cuối cùng, khối trong cùng chứa một H
chương trình tạm dừng.
Mục E
Phần E xử lý kết hợp các cặp chữ số ASCII được tạo bởi phần G và cả hai đều in ký tự được mã hóa tương ứng và gửi một khối với cặp kết hợp sang trái sang các phần C và D.
Một lần nữa dưới đây cho thấy một lần lặp điển hình với x
và y
đại diện cho mã ASCII của các chữ số.
E F
~ [+$4--498+*-:~-10)):] ) < ~ [y] [x]
) [+$4--498+*-:~-10)):] < [x] [y]
+ $4- - 498 +*- :~ -10 ) ) : [x[y]]
+--- -{-498} +*- ~~{-10} ) ) [x[y]] [x[y]]
+-- - 498 +* -{-10} ~ ) x [y] [x[y]]
+- -{-498} + * 10 x )[y] [x[y]]
+ - 498 + {10*x} y [x[y]]
+ {-498} {10*x+y} [x[y]]
{10*x+y-498} [x[y]]
[x[y]]
- Các khối chữ số đến được hoán đổi, sau đó khối y được gắn vào khối x và toàn bộ khối cặp được sao chép. Một bản sao sẽ được để lại cho đến hết phần C và D.
- Bản sao khác được gỡ rối một lần nữa, sau đó một chuỗi các hàm số học được áp dụng để tính toán
10*x+y-498
, giá trị ASCII của ký tự được mã hóa. 498 = 10*48+48-30
, 48
s hoàn tác mã hóa ASCII x
và y
trong khi 30
chuyển mã hóa từ 00–99
sang 30–129
, bao gồm tất cả ASCII có thể in được.
- Số kết quả sau đó được để lại để thực thi, in ký tự của nó.
Mục F
Phần F bao gồm các khối trơ chứa mã số ASCII. Đối với hầu hết các chương trình chạy, sẽ có nhiều nhất là hai ở đây, vì phần E tiêu thụ chúng với cùng tốc độ mà G tạo ra chúng. Tuy nhiên, trong giai đoạn in cuối cùng, một 0
số chữ số dự phòng sẽ được thu thập ở đây.
[y] [x] ...
Mục G
Phần G xử lý tách số lớn ở cuối chương trình, trước tiên là các chữ số có nghĩa ít nhất và gửi các khối có mã ASCII của chúng sang trái cho các phần khác.
Vì nó không có kiểm tra tạm dừng, nó thực sự sẽ tiếp tục tạo ra các 0
chữ số khi số đã giảm xuống 0, cho đến khi phần D tạm dừng toàn bộ chương trình với H
hàm.
[BkG]
viết tắt một bản sao của khối mã bắt đầu lớn, được sử dụng để tự sao chép để bắt đầu các lần lặp mới.
Khởi tạo trong các chu kỳ đầu tiên:
) :~ : [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ( 106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
) ~ ~ [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] [BkG] [10...11]
) [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ~ [BkG] [10...11]
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [10...11] [BkG]
Lặp lại điển hình, N
biểu thị số cần chia:
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [N] [BkG]
) :~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+ :5 ) : [N] : [BkG]
) ~ ~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] +5 5 ) [N] [N] [BkG] [BkG]
) [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] ~ 10 N [N] [BkG] [BkG]
) ~:~ ~ ( [:~)*[):~[$1(+48]):~+]-:~~)10)~~] / N 10 [N] [BkG] [BkG]
) ~ : [:~)*[):~[$1(+48]):~+]-:~~)10)~~] ( {N/10} [N] [BkG] [BkG]
) [:~)*[):~[$1(+48]):~+]-:~~)10)~~] : [{N/10}] [N] [BkG] [BkG]
:~ )*[):~[$1(+48]):~+]- :~ ~)10 ) ~ ~ [{N/10}] [{N/10}] [N] [BkG] [BkG]
~~) *[):~[$1(+48]):~+]- ~~10 ) ) [{N/10}] ~ [{N/10}] [N] [BkG] [BkG]
) ~ * [):~[$1(+48]):~+] -10 ~ ) {N/10} [N] [{N/10}] [BkG] [BkG]
) [):~[$1(+48]):~+] * {-10} {N/10} ) [N] [{N/10}] [BkG] [BkG]
) :~ [$1(+48]) :~ + {-10*(N/10)} N [{N/10}] [BkG] [BkG]
) ~ ~ [$1(+48] ) ~ ~ {N%10} [{N/10}] [BkG] [BkG]
) [$1(+48] ~ ) {N%10} ~ [{N/10}] [BkG] [BkG]
$1( + 48 {N%10} ) [BkG] [{N/10}] [BkG]
( {48+N%10} BkG [{N/10}] [BkG] New iteration starts
[{48+N%10}] ....
- Các blob chậm trễ ở đây là đặc biệt lông. Tuy nhiên, thủ thuật trì hoãn mới duy nhất là sử dụng
+:5
thay vì --10
trì hoãn 10
hai chu kỳ. Than ôi chỉ có một trong những người 10
trong chương trình được giúp đỡ bởi điều này.
- Các khối
[N]
và [BkG]
được nhân đôi, sau đó một bản sao N
được chia cho 10
.
[{N/10}]
được nhân đôi, sau đó nhiều hàm số học được sử dụng để tính mã ASCII của chữ số cuối cùng N
là as 48+((-10)*(N/10)+N)
. Khối có mã ASCII này được để lại cho phần F.
- Các bản sao khác của
[{N/10}]
được hoán đổi giữa các [BkG]
khối để thiết lập bắt đầu một lần lặp mới.
Tiền thưởng (540 byte)
)$$3371%%1[~!~~!)!]):[)$$20%%0[):]~)~~[)$$12%%0[<$$7%~~0):~[+----48+*-~~10))]<]<~!:~)~~[40~[:~))~:~[)~(~~/[+--48):]~10]+30])):]]][)[H]](11(06(06(21(21(25(19(07(07(19(61(96(03(96(96(03(11(03(63(11(28(61(11(06(06(20(18(07(07(18(61(11(28(63(96(11(96(96(61(11(06(06(19(20(07(07(18(61(30(06(06(25(07(96(96(18(11(28(96(61(13(15(15(15(15(22(26(13(12(15(96(96(19(18(11(11(63(30(63(30(96(03(28(96(11(96(96(61(22(18(96(61(28(96(11(11(96(28(96(61(11(96(10(96(96(17(61(13(15(15(22(26(11(28(63(96(19(18(63(13(21(18(63(11(11(28(63(63(63(61(11(61(42(63(63
Hãy thử trực tuyến!
Vì tôi không chắc phương thức nào sẽ ngắn nhất, trước tiên tôi đã thử mã hóa các ký tự dưới dạng các số có hai chữ số cách nhau bởi (
s. Mã lõi ngắn hơn một chút, nhưng biểu diễn dữ liệu lớn hơn 50% bù cho nó. Không chơi gôn như người khác, khi tôi dừng lại khi nhận ra nó sẽ không đánh bại nó. Nó có một lợi thế: Nó không yêu cầu triển khai với sự hỗ trợ của bignum.
Cấu trúc tổng thể của nó là hơi giống với cấu trúc chính. Phần G bị thiếu do biểu diễn dữ liệu điền trực tiếp vào phần F. Tuy nhiên, phần E phải thực hiện phép tính divmod tương tự để xây dựng lại các chữ số của các số có hai chữ số.