Khối, 33 32 byte
u*.$s.!(.01I^<W%NW!;<,;;q+p@Opus
Hình thức mạng:
u * .
$ s .
! ( .
0 1 I ^ < W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
. . .
. . .
. . .
Hãy thử trực tuyến!
Ghi chú
- Hoạt động với đầu vào lên đến 170, đầu vào cao hơn dẫn đến một vòng lặp vô hạn, bởi vì giai thừa của chúng mang lại
Infinity
số (nói về mặt kỹ thuật, đây là thuộc tính không thể ghi, không thể đếm được và không thể cấu hình của đối tượng cửa sổ).
- Độ chính xác bị mất cho đầu vào 19 trở lên, vì các số cao hơn 2 53 (= 9 007 199 254 740 992) không thể được lưu trữ chính xác trong JavaScript.
Giải trình
Chương trình này bao gồm hai vòng. Đầu tiên tính giai thừa của đầu vào, cái còn lại chia kết quả thành các chữ số của nó và cộng các số đó lại với nhau. Sau đó, tổng được in, và chương trình kết thúc.
Khởi đầu
Đầu tiên, chúng ta cần chuẩn bị ngăn xếp. Đối với phần đó, chúng tôi sử dụng ba hướng dẫn đầu tiên. IP bắt đầu trên dòng thứ tư, chỉ về phía đông. Ngăn xếp trống rỗng.
. . .
. . .
. . .
0 1 I . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .
Chúng tôi sẽ giữ tổng số ở dưới cùng của ngăn xếp, vì vậy chúng tôi cần bắt đầu với 0
tổng bằng cách lưu trữ số đó ở dưới cùng của ngăn xếp. Sau đó, chúng ta cần phải đẩy một1
, vì đầu vào ban đầu sẽ được nhân với số trước nó. Nếu đây là 0, giai thừa sẽ luôn mang lại số không. Cuối cùng, chúng tôi đọc đầu vào như một số nguyên.
Bây giờ, ngăn xếp là [0, 1, input]
và IP ở dòng thứ tư, cột thứ tư, chỉ về phía đông.
Vòng lặp nhân tố
Đây là một vòng lặp đơn giản nhân hai phần tử trên cùng của ngăn xếp (kết quả của vòng lặp trước và đầu vào - n, sau đó giảm đầu vào. Nó bị ngắt khi đầu vào đạt 0. Lệnh $
khiến IP bỏ qua u
- lần lượt. Vòng lặp là phần sau của khối. IP bắt đầu trên dòng thứ tư, cột thứ tư.
u * .
$ s .
! ( .
. . . ^ < . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .
Vì ^
đặc tính, IP bắt đầu di chuyển về phía bắc ngay lập tức. Sau đó, u
xoay IP xung quanh và di chuyển nó sang bên phải. Ở phía dưới, có một mũi tên khác: <
trỏ IP trở lại vào ^
. Ngăn xếp bắt đầu như [previousresult, input-n]
, nơi n
là số lần lặp lại. Các ký tự sau được thực thi trong vòng lặp:
*s(
* # Multiply the top two items
# Stack: [previousresult, input-n, newresult]
s # Swap the top two items
# Stack: [previousresult, newresult, input-n]
( # Decrement the top item
# Stack: [previousresult, newresult, input-n-1]
Sau đó, đỉnh của ngăn xếp (đầu vào giảm) được kiểm tra 0
theo !
hướng dẫn và nếu có 0
,u
ký tự sẽ bị bỏ qua.
Tổng các chữ số
IP bao quanh khối lập phương, kết thúc ở ký tự cuối cùng trên dòng thứ tư, ban đầu chỉ về phía tây. Vòng lặp sau bao gồm khá nhiều tất cả các ký tự còn lại:
. . .
. . .
. . .
. . . . . W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
. . .
. . .
. . .
Vòng lặp trước tiên xóa mục trên cùng khỏi ngăn xếp (là một trong hai 10
hoặc 0
), sau đó kiểm tra những gì còn lại của kết quả của giai thừa. Nếu điều đó đã được giảm xuống 0
, phần dưới cùng của ngăn xếp (tổng) được in và chương trình dừng lại. Mặt khác, các hướng dẫn sau đây được thực thi (ngăn xếp bắt đầu như [oldsum, ..., factorial]
):
N%p+q;;,s;
N # Push 10
# Stack: [oldsum, ..., factorial, 10]
% # Push factorial % 10
# Stack: [oldsum, ..., factorial, 10, factorial % 10]
p # Take the sum to the top
# Stack: [..., factorial, 10, factorial % 10, oldsum]
+ # Add top items together
# Stack: [..., factorial, 10, factorial % 10, oldsum, newsum]
q # Send that to the bottom
# Stack: [newsum, ..., factorial, 10, factorial % 10, oldsum]
;; # Delete top two items
# Stack: [newsum, ..., factorial, 10]
, # Integer divide top two items
# Stack: [newsum, ..., factorial, 10, factorial/10]
s; # Delete the second item
# Stack: [newsum, ..., factorial, factorial/10]
Và vòng lặp bắt đầu lại, cho đến khi factorial/10
bằng 0.
n>21