Phân hạch , 1328 989 887 797 byte
Câu trả lời này hơi dài một cách vô lý (tôi ước chúng ta có những vùng bị sụp đổ ) ... xin đừng quên cuộn qua cái này và cho những câu trả lời khác một số tình yêu!
Làm việc trên mã này là những gì đã truyền cảm hứng cho thách thức này. Tôi muốn thêm một câu trả lời trong Phân hạch vào EOEIS, điều này dẫn tôi đến trình tự này. Tuy nhiên, thực sự học Phân hạch và thực hiện việc này mất vài tuần để thực hiện và tắt nó. Trong khi đó, trình tự đã thực sự phát triển trong tôi nên tôi quyết định đăng một thử thách riêng cho nó (cộng với, điều này sẽ không đặc biệt ở xa cây trên EOEIS).
Vì vậy, tôi trình bày với bạn, sự quái dị:
R'0@+\
/ Y@</ /[@ Y]_L
[? % \ / \ J
\$@ [Z/;[{+++++++++L
UR+++++++++>/;
9\ ; 7A9
SQS {+L /$ \/\/\/\/\/ 5/ @ [~ &@[S\/ \ D /8/
~4X /A@[ %5 /; & K } [S//~KSA /
3 \ A$@S S\/ \/\/\/ \/>\ /S]@A / \ { +X
W7 X X /> \ +\ A\ / \ /6~@/ \/
/ ~A\; +;\ /@
ZX [K / {/ / @ @ } \ X @
\AS </ \V / }SZS S/
X ;;@\ /;X /> \ ; X X
; \@+ >/ }$S SZS\+; //\V
/ \\ /\; X X @ @ \~K{
\0X / /~/V\V / 0W//
\ Z [K \ //\
W /MJ $$\\ /\7\A /;7/\/ /
4}K~@\ &] @\ 3/\
/ \{ }$A/1 2 }Y~K <\
[{/\ ;@\@ / \@<+@^ 1;}++@S68
@\ <\ 2 ; \ /
$ ;}++ +++++++L
%@A{/
M \@+>/
~ @
SNR'0YK
\ A!/
Nó hy vọng rằng không có dòng mới trên đầu vào, vì vậy bạn có thể muốn gọi nó như thế nào echo -n 120 | ./Fission oeis256504.fis
.
Bố cục có thể vẫn hiệu quả hơn, vì vậy tôi nghĩ vẫn còn nhiều chỗ để cải thiện ở đây (ví dụ: cái này chứa 911 581 461 374 khoảng trắng).
Trước khi chúng tôi có được lời giải thích, một lưu ý khi kiểm tra điều này: thông dịch viên chính thức không hoàn toàn hoạt động như hiện tại. a) Mirror.cpp
không biên dịch trên nhiều hệ thống. Nếu bạn gặp phải vấn đề đó, chỉ cần nhận xét dòng vi phạm - thành phần bị ảnh hưởng (một máy nhân bản ngẫu nhiên) không được sử dụng trong mã này. b) Có một vài lỗi có thể dẫn đến hành vi không xác định (và có khả năng sẽ xảy ra đối với một chương trình phức tạp này). Bạn có thể áp dụng bản vá này để sửa chúng. Khi bạn đã thực hiện điều đó, bạn sẽ có thể biên dịch trình thông dịch với
g++ -g --std=c++11 *.cpp -o Fission
Sự thật thú vị: Chương trình này sử dụng hầu hết mọi phân hạch thành phần, ngoại trừ #
(gương ngẫu nhiên), :
(gương nửa) -
hoặc |
(gương đơn giản) và "
(chế độ in).
Những gì trên trái đất?
Cảnh báo: Việc này sẽ khá lâu ... Tôi cho rằng bạn thực sự quan tâm đến cách thức Phân hạch hoạt động và cách người ta có thể lập trình trong đó. Bởi vì nếu bạn không, tôi không chắc làm thế nào tôi có thể tóm tắt điều này. (Đoạn tiếp theo đưa ra một mô tả chung về ngôn ngữ.)
Phân hạch là ngôn ngữ lập trình hai chiều, trong đó cả dữ liệu và luồng điều khiển được thể hiện bằng các nguyên tử di chuyển qua lưới. Nếu bạn đã thấy hoặc sử dụng Marbelous trước đây, khái niệm này sẽ rất quen thuộc. Mỗi nguyên tử có hai tính chất nguyên: khối lượng không âm và năng lượng tùy ý. Nếu khối lượng trở nên âm, nguyên tử được loại bỏ khỏi lưới điện. Trong hầu hết các trường hợp, bạn có thể coi khối lượng là "giá trị" của nguyên tử và năng lượng như một loại thuộc tính meta được sử dụng bởi một số thành phần để xác định dòng chảy của các nguyên tử (nghĩa là hầu hết các loại công tắc phụ thuộc vào dấu hiệu của năng lượng). Tôi sẽ ký hiệu các nguyên tử bằng (m,E)
, khi cần thiết. Khi bắt đầu chương trình, lưới bắt đầu với một loạt(1,0)
các nguyên tử từ bất cứ nơi nào bạn đặt trên bốn thành phần UDLR
(trong đó chữ cái chỉ hướng nguyên tử đang di chuyển ban đầu). Hội đồng sau đó được tập hợp với một loạt các thành phần làm thay đổi khối lượng và năng lượng của các nguyên tử, thay đổi hướng của chúng hoặc làm những việc phức tạp hơn khác. Để biết danh sách đầy đủ, hãy xem trang esolang , nhưng tôi sẽ giới thiệu hầu hết trong số đó trong phần giải thích này. Một điểm quan trọng khác (mà chương trình sử dụng nhiều lần) là lưới hình xuyến: một nguyên tử va vào bất kỳ phía nào xuất hiện ở phía đối diện, di chuyển theo cùng một hướng.
Tôi đã viết chương trình thành nhiều phần nhỏ hơn và tập hợp chúng vào cuối, vì vậy đó là cách tôi sẽ giải thích.
atoi
Thành phần này có vẻ không thú vị, nhưng nó hay và đơn giản và cho phép tôi giới thiệu rất nhiều khái niệm quan trọng về dòng số học và kiểm soát của Fudge. Do đó, tôi sẽ xem xét phần này một cách khá chi tiết, vì vậy tôi có thể giảm các phần khác để giới thiệu cơ học phân hạch mới và chỉ ra các thành phần cấp cao hơn có luồng điều khiển chi tiết mà bạn có thể tự theo dõi.
Phân hạch chỉ có thể đọc các giá trị byte từ các ký tự riêng lẻ, không phải toàn bộ số. Trong khi đó thực tế có thể chấp nhận được ở đây, tôi đã hình dung khi tôi ở đó, tôi có thể làm đúng và phân tích các số nguyên thực tế trên STDIN. Đây là atoi
mã:
;
R'0@+\
/ Y@</ /[@ Y]_L
[? % \ / \ J
\$@ [Z/;[{+++++++++L
UR+++++++++>/;
O
Hai trong số các thành phần quan trọng nhất trong phân hạch là lò phản ứng phân hạch và phản ứng tổng hợp. Lò phản ứng phân hạch là bất kỳ V^<>
(mã trên sử dụng <
và >
). Một lò phản ứng phân hạch có thể lưu trữ một nguyên tử (bằng cách gửi nó vào nêm của nhân vật), mặc định (2,0)
. Nếu một nguyên tử chạm vào đỉnh của nhân vật, hai nguyên tử mới sẽ được gửi sang hai bên. Khối lượng của chúng được xác định bằng cách chia khối lượng đến cho khối lượng được lưu trữ (nghĩa là giảm một nửa theo mặc định) - nguyên tử đi bên trái có giá trị này và nguyên tử đi phải lấy phần còn lại (nghĩa là khối lượng được bảo toàn trong phân hạch) . Cả hai nguyên tử đi sẽ có âm năng lượng đếnnăng lượng dự trữ. Điều này có nghĩa là chúng ta có thể sử dụng các lò phản ứng phân hạch cho số học - cả cho phép trừ và chia. Nếu một lò phản ứng phân hạch được đánh từ trang web, nguyên tử chỉ được phản xạ theo đường chéo và sau đó sẽ di chuyển theo hướng đỉnh của nhân vật.
Lò phản ứng nhiệt hạch là bất kỳ YA{}
(mã trên sử dụng Y
và {
). Chức năng của chúng tương tự nhau: chúng có thể lưu trữ một nguyên tử (mặc định (1,0)
) và khi bị tấn công từ đỉnh, hai nguyên tử mới sẽ được gửi sang hai bên. Tuy nhiên, trong trường hợp này, hai nguyên tử sẽ giống hệt nhau, luôn giữ lại năng lượng đến và nhân khối lượng đến với khối lượng được lưu trữ. Theo mặc định, lò phản ứng nhiệt hạch chỉ đơn giản là sao chép bất kỳ nguyên tử nào chạm đỉnh của nó. Khi bị tấn công từ hai bên, các lò phản ứng nhiệt hạch phức tạp hơn một chút: nguyên tử cũng vậyđược lưu trữ (độc lập với bộ nhớ khác) cho đến khi một nguyên tử chạm vào phía đối diện. Khi điều đó xảy ra, một nguyên tử mới được giải phóng theo hướng của đỉnh có khối lượng và năng lượng là tổng của hai nguyên tử cũ. Nếu một nguyên tử mới chạm vào cùng một phía trước khi một nguyên tử phù hợp đến phía đối diện, nguyên tử cũ sẽ đơn giản bị ghi đè. Lò phản ứng nhiệt hạch có thể được sử dụng để thực hiện phép cộng và nhân.
Một thành phần đơn giản khác mà tôi muốn tránh ra là [
và ]
đơn giản là đặt hướng của nguyên tử sang phải và trái, tương ứng (bất kể hướng đến). Tương đương dọc là M
(xuống) và W
(lên) nhưng chúng không được sử dụng cho atoi
mã. UDLR
cũng hoạt động như WM][
sau khi phát hành các nguyên tử ban đầu của chúng.
Dù sao, hãy nhìn vào mã trên đó. Chương trình bắt đầu với 5 nguyên tử:
- Các
R
và L
ở phía dưới chỉ đơn giản là có được tăng khối lượng của chúng (với +
) để trở thành (10,0)
và sau đó lưu trữ trong một phân hạch và một lò phản ứng nhiệt hạch, tương ứng. Chúng tôi sẽ sử dụng các lò phản ứng này để phân tích đầu vào cơ sở 10.
- Ở
L
góc trên bên phải sẽ giảm khối lượng (với _
) để trở thành (0,0)
và được lưu trữ ở bên cạnh lò phản ứng nhiệt hạch Y
. Điều này là để theo dõi số lượng chúng ta đang đọc - chúng ta sẽ tăng dần và nhân số này khi chúng ta đọc số.
- Góc
R
trên bên trái được đặt khối lượng của nó thành mã ký tự của 0
(48) với '0
, sau đó khối lượng và năng lượng được hoán đổi @
và cuối cùng tăng khối lượng một lần khi +
cho (1,48)
. Sau đó, nó được chuyển hướng với gương chéo \
và /
được lưu trữ trong lò phản ứng phân hạch. Chúng tôi sẽ sử dụng 48
phép trừ để biến đầu vào ASCII thành giá trị thực của các chữ số. Chúng tôi cũng phải tăng khối lượng 1
để tránh chia rẽ 0
.
- Cuối cùng,
U
ở góc dưới bên trái là thứ thực sự khiến mọi thứ chuyển động và ban đầu chỉ được sử dụng cho luồng điều khiển.
Sau khi được chuyển hướng sang phải, nguyên tử điều khiển va vào ?
. Đây là thành phần đầu vào. Nó đọc một ký tự và đặt khối lượng của nguyên tử thành giá trị đọc ASCII và năng lượng 0
. Nếu chúng ta nhấn EOF thay vào đó, năng lượng sẽ được đặt thành 1
.
Nguyên tử tiếp tục và sau đó đánh %
. Đây là một công tắc gương. Đối với năng lượng không tích cực, điều này hoạt động như một /
tấm gương. Nhưng đối với năng lượng tích cực, nó hoạt động như một \
(và cũng làm giảm năng lượng đi 1). Vì vậy, trong khi chúng ta đọc các ký tự, nguyên tử sẽ được phản xạ lên trên và chúng ta có thể xử lý ký tự. Nhưng khi chúng ta thực hiện xong đầu vào, nguyên tử sẽ được phản xạ xuống và chúng ta có thể áp dụng logic khác nhau để lấy kết quả. FYI, thành phần ngược lại là &
.
Vì vậy, bây giờ chúng ta đã có một nguyên tử di chuyển lên. Những gì chúng tôi muốn làm cho mỗi ký tự là đọc giá trị chữ số của nó, thêm nó vào tổng số đang chạy của chúng tôi và sau đó nhân tổng số chạy đó với 10 để chuẩn bị cho chữ số tiếp theo.
Nguyên tử nhân vật đầu tiên chạm vào lò phản ứng nhiệt hạch (mặc định) Y
. Điều này phân tách nguyên tử và chúng tôi sử dụng bản sao bên trái làm nguyên tử điều khiển để lặp lại thành phần đầu vào và đọc ký tự tiếp theo. Các bản sao phải sẽ được xử lý. Hãy xem xét trường hợp chúng ta đã đọc nhân vật 3
. Nguyên tử của chúng ta sẽ là (51,0)
. Chúng ta trao đổi khối lượng và năng lượng với @
, để chúng ta có thể sử dụng phép trừ của lò phản ứng phân hạch tiếp theo. Lò phản ứng trừ 48
đi năng lượng (không thay đổi khối lượng), do đó, nó gửi đi hai bản sao (0,3)
- năng lượng hiện tương ứng với chữ số chúng ta đã đọc. Bản sao đi lên chỉ đơn giản là bị loại bỏ ;
(một thành phần chỉ phá hủy tất cả các nguyên tử đến). Chúng tôi sẽ tiếp tục làm việc với bản sao hạ cấp. Bạn sẽ cần đi theo con đường của nó thông qua/
và \
gương một chút.
Ngay @
trước khi lò phản ứng nhiệt hạch hoán đổi khối lượng và năng lượng một lần nữa, như vậy chúng ta sẽ thêm (3,0)
vào tổng số hoạt động của chúng ta trong Y
. Lưu ý rằng tổng số chạy chính nó sẽ luôn luôn có 0
năng lượng.
Bây giờ J
là một bước nhảy. Những gì nó làm là nhảy bất kỳ nguyên tử tới bằng năng lượng của nó. Nếu đó là 0
, nguyên tử cứ tiếp tục đi thẳng. Nếu nó 1
sẽ bỏ qua một ô, nếu 2
nó sẽ bỏ qua hai ô và cứ thế. Năng lượng được sử dụng trong bước nhảy, vì vậy nguyên tử luôn kết thúc bằng năng lượng 0
. Vì tổng số chạy không có năng lượng bằng không, nên hiện tại bước nhảy bị bỏ qua và nguyên tử được chuyển hướng vào lò phản ứng nhiệt hạch {
nhân khối lượng của nó lên gấp bội 10
. Bản sao hạ cấp bị loại bỏ ;
trong khi bản sao đi lên được đưa trở lại vào Y
lò phản ứng dưới dạng tổng số mới đang chạy.
Những điều trên cứ lặp đi lặp lại (theo cách ngộ nghĩnh trong đó các chữ số mới đang được xử lý trước khi các chữ số trước được thực hiện) cho đến khi chúng ta nhấn EOF. Bây giờ %
sẽ gửi nguyên tử xuống dưới. Ý tưởng là biến nguyên tử này thành (0,1)
bây giờ trước khi chạm vào tổng lò phản ứng đang chạy để a) tổng số không bị ảnh hưởng (khối lượng bằng không) và b) chúng ta có được năng lượng 1
để nhảy qua [
. Chúng ta có thể dễ dàng chăm sóc năng lượng $
, làm tăng năng lượng.
Vấn đề là ?
không thiết lập lại khối lượng khi bạn nhấn EOF nên khối lượng vẫn sẽ là ký tự cuối cùng được đọc và năng lượng sẽ là 0
(vì %
giảm dần 1
về phía sau 0
). Vì vậy, chúng tôi muốn thoát khỏi khối lượng đó. Để làm điều đó, chúng tôi trao đổi khối lượng và năng lượng với @
một lần nữa.
Tôi cần giới thiệu thêm một thành phần trước khi hoàn thành phần này : Z
. Điều này về cơ bản giống như %
hoặc &
. Sự khác biệt là nó cho phép các nguyên tử năng lượng dương đi thẳng qua (trong khi làm giảm năng lượng) và làm chệch hướng các nguyên tử năng lượng không tích cực 90 độ về bên trái. Chúng ta có thể sử dụng điều này để loại bỏ năng lượng của một nguyên tử bằng cách lặp đi lặp lại Z
nhiều lần - ngay khi hết năng lượng, nguyên tử sẽ bị lệch và rời khỏi vòng lặp. Đó là mô hình này:
/ \
[Z/
trong đó nguyên tử sẽ di chuyển lên trên một khi năng lượng bằng không. Tôi sẽ sử dụng mô hình này ở dạng này hoặc dạng khác nhiều lần trong các phần khác của chương trình.
Vì vậy, khi các nguyên tử rời khỏi vòng lặp này chút, nó sẽ được (1,0)
và hoán đổi để (0,1)
theo @
trước khi nhấn lò phản ứng tổng hợp để phát hành kết quả cuối cùng của các đầu vào. Tuy nhiên, tổng số hoạt động sẽ bị tắt bởi hệ số 10, vì chúng tôi đã nhân rộng nó cho một chữ số khác.
Vì vậy, bây giờ với năng lượng 1
, nguyên tử này sẽ bỏ qua [
và nhảy vào /
. Điều này làm chệch hướng nó thành một lò phản ứng phân hạch mà chúng tôi đã chuẩn bị chia cho 10 và khắc phục sự nhân lên của chúng tôi. Một lần nữa, chúng ta loại bỏ một nửa với ;
và giữ cho nửa kia là đầu ra (ở đây được biểu thị bằng O
cách đơn giản là in ký tự tương ứng và phá hủy nguyên tử - trong toàn bộ chương trình chúng ta tiếp tục sử dụng nguyên tử thay thế).
itoa
/ \
input -> [{/\ ;@
@\ <\
$ ;}++ +++++++L
%@A{/
M \@+>/
~ @
SNR'0YK
\ A!/
Tất nhiên, chúng ta cũng cần chuyển đổi kết quả trở lại thành một chuỗi và in nó. Đó là những gì phần này dành cho. Điều này giả định rằng đầu vào không đến trước 10 hoặc hơn, nhưng trong chương trình đầy đủ dễ dàng được đưa ra. Bit này có thể được tìm thấy ở dưới cùng của chương trình đầy đủ.
Mã này giới thiệu một thành phần Phân hạch rất mạnh mới: ngăn xếp K
. Các ngăn xếp ban đầu là trống rỗng. Khi một nguyên tử có năng lượng không âm chạm vào ngăn xếp, nguyên tử chỉ đơn giản được đẩy lên ngăn xếp. Khi một nguyên tử có năng lượng âm chạm vào ngăn xếp, khối lượng và năng lượng của nó sẽ được thay thế bằng nguyên tử trên đỉnh của ngăn xếp (do đó được bật lên). Nếu ngăn xếp trống rỗng, hướng của nguyên tử bị đảo ngược và năng lượng của nó trở nên tích cực (tức là được nhân với -1
).
Được rồi, trở lại mã thực tế. Ý tưởng của itoa
đoạn trích là liên tục lấy modulo đầu vào 10 để tìm chữ số tiếp theo trong khi chia số nguyên cho 10 cho lần lặp tiếp theo. Điều này sẽ mang lại tất cả các chữ số theo thứ tự ngược lại (từ ít quan trọng nhất đến quan trọng nhất). Để khắc phục thứ tự, chúng tôi đẩy tất cả các chữ số lên một chồng và cuối cùng bật chúng ra từng cái một để in chúng.
Nửa trên của mã thực hiện tính toán chữ số: L
với các điểm cộng cho 10 mà chúng ta nhân bản và đưa vào phản ứng phân hạch và phản ứng tổng hợp để chúng ta có thể chia và nhân với 10. Vòng lặp về cơ bản bắt đầu sau [
góc trên cùng bên trái . Giá trị hiện tại được phân chia: một bản sao được chia cho 10, sau đó nhân với 10 và được lưu trữ trong lò phản ứng phân hạch, sau đó được sao chép bởi bản sao khác ở đỉnh. Điều này tính toán i % 10
như i - ((i/10) * 10)
. Cũng lưu ý rằng việc A
chia kết quả trung gian sau khi chia và trước khi nhân, để chúng ta có thể i / 10
đưa vào lần lặp tiếp theo.
Việc %
hủy bỏ vòng lặp một khi biến lặp lặp đạt 0. Vì đây ít nhiều là vòng lặp do-while, mã này thậm chí sẽ hoạt động để in 0
(mà không tạo ra các số 0 khác đi). Khi chúng ta rời khỏi vòng lặp, chúng ta muốn làm trống ngăn xếp và in các chữ số. S
ngược lại Z
, do đó, nó là một công tắc sẽ làm chệch hướng một nguyên tử tới với năng lượng không dương 90 độ về bên phải. Vì vậy, nguyên tử thực sự di chuyển qua các cạnh từ S
thẳng K
đến bật ra một chữ số (lưu ý rằng ~
điều này đảm bảo rằng nguyên tử đến có năng lượng -1
). Chữ số đó được tăng lên 48
để có được mã ASCII của ký tự chữ số tương ứng. Chữ số A
tách chữ số để in một bản sao với!
và đưa bản sao khác trở lại vào Y
lò phản ứng cho chữ số tiếp theo. Bản sao được in được sử dụng làm trình kích hoạt tiếp theo cho ngăn xếp (lưu ý rằng các gương cũng gửi nó xung quanh cạnh để đánh M
từ bên trái).
Khi ngăn xếp trống rỗng, ý K
chí sẽ phản ánh nguyên tử và biến năng lượng của nó thành +1
, sao cho nó đi thẳng qua S
. N
in một dòng mới (chỉ vì nó gọn gàng :)). Và sau đó nguyên tử đi vào ngực R'0
một lần nữa để kết thúc ở bên cạnh Y
. Vì không còn nguyên tử nào nữa, điều này sẽ không bao giờ được phát hành và chương trình chấm dứt.
Tính toán số phân hạch: Khung
Hãy đến với phần thịt thực sự của chương trình. Mã về cơ bản là một cổng triển khai tham chiếu Mathicala của tôi:
fission[n_] := If[
(div =
SelectFirst[
Reverse@Divisors[2 n],
(OddQ@# == IntegerQ[n/#]
&& n/# > (# - 1)/2) &
]
) == 1,
1,
1 + Total[fission /@ (Range@div + n/div - (div + 1)/2)]
]
trong đó div
số lượng số nguyên trong phân vùng tối đa.
Sự khác biệt chính là chúng ta không thể xử lý các giá trị nửa nguyên trong Phân hạch, vì vậy tôi đang làm rất nhiều thứ nhân với hai và không có đệ quy trong Phân hạch. Để giải quyết vấn đề này, tôi sẽ đẩy tất cả các số nguyên trong một phân vùng trong hàng đợi để được xử lý sau. Đối với mỗi số chúng tôi xử lý, chúng tôi sẽ tăng một bộ đếm lên một và khi hàng đợi trống, chúng tôi sẽ giải phóng bộ đếm và gửi đi để được in. (Một hàng đợi, Q
hoạt động chính xác như thế K
, chỉ theo thứ tự FIFO.)
Đây là một khuôn khổ cho khái niệm này:
+--- input goes in here
v
SQS ---> compute div from n D /8/
~4X | /~KSA /
3 +-----------> { +X
initial trigger ---> W 6~@/ \/
4
W ^ /
| 3
^ generate range |
| from n and div <-+----- S6
| -then-
+---- release new trigger
Các thành phần mới quan trọng nhất là các chữ số. Đây là những người dịch chuyển tức thời. Tất cả các dịch chuyển tức thời với cùng một chữ số thuộc về nhau. Khi một nguyên tử chạm vào bất kỳ dịch chuyển tức thời nào, nó sẽ ngay lập tức di chuyển dịch chuyển tức thời tiếp theo trong cùng một nhóm, trong đó tiếp theo được xác định theo thứ tự từ trái sang phải, từ trên xuống dưới thông thường. Đây không phải là cần thiết, nhưng giúp bố trí (và do đó chơi golf một chút). Ngoài ra còn X
có cách đơn giản là sao chép một nguyên tử, gửi một bản sao thẳng về phía trước và bản kia ngược lại.
Bây giờ bạn có thể tự mình sắp xếp hầu hết các khung. Góc trên bên trái có hàng đợi các giá trị vẫn được xử lý và giải phóng từng giá trị n
một. Một bản sao n
được dịch chuyển xuống dưới cùng vì chúng ta cần nó khi tính toán phạm vi, bản sao khác đi vào khối ở trên cùng để tính toán div
(đây là phần lớn nhất của mã). Khi div
đã được tính toán, nó được nhân đôi - một bản sao tăng một bộ đếm ở góc trên cùng bên phải, được lưu trữ trong K
. Các bản sao khác được dịch chuyển xuống dưới cùng. Nếu div
là 1
, chúng ta làm chệch hướng nó lên ngay lập tức và sử dụng nó như một trình kích hoạt cho lần lặp tiếp theo, mà không làm mất đi bất kỳ giá trị mới nào. Nếu không, chúng tôi sử dụng div
vàn
trong phần ở phía dưới để tạo phạm vi mới (nghĩa là một luồng nguyên tử có khối lượng tương ứng được đặt trong hàng đợi), sau đó giải phóng một bộ kích hoạt mới sau khi phạm vi đã hoàn thành.
Khi hàng đợi trống, kích hoạt sẽ được phản ánh, đi thẳng qua S
và xuất hiện lại ở góc trên cùng bên phải, nơi nó giải phóng bộ đếm (kết quả cuối cùng) từ A
đó, sau đó được dịch chuyển itoa
qua 8
.
Tính toán số phân hạch: Thân vòng
Vì vậy, tất cả những gì còn lại là hai phần để tính toán div
và tạo phạm vi. Máy tính div
là phần này:
;
{+L /$ \/\/\/\/\/ 5/ @ [~ &@[S\/ \
/A@[ %5 /; & K } [S/
\ A$@S S\/ \/\/\/ \/>\ /S]@A / \
X X /> \ +\ A\ / \ /
/ ~A\; +;\ /@
ZX [K / {/ / @ @ } \ X @
\AS </ \V / }SZS S/
X ;;@\ /;X /> \ ; X X
\@+ >/ }$S SZS\+; //\V
/ \\ /\; X X @ @ \~K{
\0X / /~/V\V / 0W//
\ Z [K \ //\
\ /\7\A /;7/\/
Bây giờ bạn có thể thấy đủ để đánh đố điều này với chính mình với một chút kiên nhẫn. Bảng phân tích cấp cao là thế này: 12 cột đầu tiên hoặc lâu hơn tạo ra một luồng các ước số của 2n
. 10 cột tiếp theo lọc ra những cột không thỏa mãn OddQ@# == IntegerQ[n/#]
. 8 cột tiếp theo lọc ra những cột không thỏa mãn n/# > (# - 1)/2)
. Cuối cùng, chúng tôi đẩy tất cả các ước số hợp lệ lên một ngăn xếp và sau khi hoàn thành, chúng tôi đổ toàn bộ ngăn xếp vào một lò phản ứng tổng hợp (ghi đè lên tất cả trừ ước số cuối cùng / lớn nhất) và sau đó giải phóng kết quả, sau đó loại bỏ năng lượng của nó (không phải là năng lượng của nó -zero từ việc kiểm tra bất đẳng thức).
Có rất nhiều con đường điên rồ trong đó không thực sự làm gì cả. Chủ yếu, sự \/\/\/\/
điên rồ ở phía trên ( 5
s cũng là một phần của nó) và một con đường xung quanh phía dưới (đi qua 7
s). Tôi đã phải thêm những thứ này để đối phó với một số điều kiện cuộc đua khó chịu. Phân hạch có thể sử dụng một thành phần trì hoãn ...
Mã tạo ra phạm vi mới từ n
và div
là:
/MJ $$\
4}K~@\ &] @\ 3/\
\{ }$A/1 2 }Y~K <\
\@ / \@<+@^ 1;}++@
2 ; \ /
Trước tiên, chúng tôi tính toán n/div - (div + 1)/2
(cả hai thuật ngữ thả nổi, mang lại kết quả tương tự) và lưu trữ cho lần sau. Sau đó, chúng tôi tạo ra một phạm vi từ div
xuống đến 1
và thêm giá trị được lưu trữ cho mỗi trong số chúng.
Có hai mô hình phổ biến mới trong cả hai mô hình này, mà tôi nên đề cập: Một là SX
hoặc ZX
đánh từ bên dưới (hoặc các phiên bản xoay). Đây là một cách hay để sao chép một nguyên tử nếu bạn muốn một bản sao đi thẳng (vì việc chuyển hướng đầu ra của lò phản ứng nhiệt hạch đôi khi có thể trở nên cồng kềnh). Các S
hoặc Z
quay nguyên tử vào X
và sau đó quay trở lại bản sao nhân đôi vào hướng ban đầu của công tác tuyên truyền.
Các mô hình khác là
[K
\A --> output
Nếu chúng ta lưu trữ bất kỳ giá trị nào trong K
chúng ta có thể lấy lại nó bằng cách đánh K
với năng lượng âm từ trên xuống. Các A
bản sao giá trị mà chúng ta quan tâm và gửi bản sao ngay vào ngăn xếp cho lần tiếp theo chúng ta cần.
Chà, đó là một cuốn sách khá hay ... nhưng nếu bạn thực sự vượt qua được điều này, tôi hy vọng bạn có ý tưởng rằng Fudge i͝s̢̘̗̗ i̟nç̮̩r̸̭̬̱͔e̟̹̟̜͟d̙i̠͙͎̖͓̯b̘̠͎̭̰̼l̶̪̙̮̥̮y̠̠͎̺͜ ͚̬̮f̟͞u̱̦̰͍n͍ ̜̠̙t̸̳̩̝o ̫͉̙͠p̯̱̭͙̜͙͞ŕ̮͓̜o̢̙̣̭g̩̼̣̝r