Cubix, 33 32 bytes
u*.$s.!(.01I^<W%NW!;<,;;q+p@Opus
Net form:
u * .
$ s .
! ( .
0 1 I ^ < W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
. . .
. . .
. . .
Try it online!
Notes
- Works with inputs up to and including 170, higher inputs result in an infinite loop, because their factorial yields the
Infinity
number (technically speaking, its a non-writable, non-enumerable and non-configurable property of the window object).
- Accuracy is lost for inputs 19 and up, because numbers higher than 253 (= 9 007 199 254 740 992) cannot be accurately stored in JavaScript.
Explanation
This program consists of two loops. The first calculates the factorial of the input, the other splits the result into its digits and adds those together. Then the sum is printed, and the program finishes.
Start
First, we need to prepare the stack. For that part, we use the first three instructions. The IP starts on the fourth line, pointing east. The stack is empty.
. . .
. . .
. . .
0 1 I . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .
We will keep the sum at the very bottom of the stack, so we need to start with 0
being the sum by storing that on the bottom of the stack. Then we need to push a 1
, because the input will initially be multiplied by the number before it. If this were zero, the factorial would always yield zero as well. Lastly we read the input as an integer.
Now, the stack is [0, 1, input]
and the IP is at the fourth line, the fourth column, pointing east.
Factorial loop
This is a simple loop that multiplies the top two elements of the stack (the result of the previous loop and the input - n, and then decrements the input. It breaks when the input reaches 0. The $
instruction causes the IP to skip the u
-turn. The loop is the following part of the cube. The IP starts on the fourth line, fourth column.
u * .
$ s .
! ( .
. . . ^ < . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .
Because of the ^
character, the IP starts moving north immediately. Then the u
turns the IP around and moves it one to the right. At the bottom, there's another arrow: <
points the IP back into the ^
. The stack starts as [previousresult, input-n]
, where n
is the number of iterations. The following characters are executed in the loop:
*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]
Then the top of the stack (decreased input) is checked against 0
by the !
instruction, and if it is 0
, the u
character is skipped.
Sum the digits
The IP wraps around the cube, ending up on the very last character on the fourth line, initially pointing west. The following loop consists of pretty much all remaining characters:
. . .
. . .
. . .
. . . . . W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
. . .
. . .
. . .
The loop first deletes the top item from the stack (which is either 10
or 0
), and then checks what is left of the result of the factorial. If that has been decreased to 0
, the bottom of the stack (the sum) is printed and the program stops. Otherwise, the following instructions get executed (stack starts as [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]
And the loop starts again, until factorial/10
equals 0.
n>21
\$\endgroup\$