Cubix, 33 32 байта
u*.$s.!(.01I^<W%NW!;<,;;q+p@Opus
Чистая форма:
u * .
$ s .
! ( .
0 1 I ^ < W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
. . .
. . .
. . .
Попробуйте онлайн!
Заметки
- Работает со входами до 170 включительно, более высокие входы приводят к бесконечному циклу, потому что их факториал дает
Infinity
число (технически говоря, это не записываемое, не перечисляемое и не конфигурируемое свойство объекта окна).
- Точность теряется для входных данных 19 и выше, потому что числа выше 2 53 (= 9 007 199 254 740 992) не могут быть точно сохранены в JavaScript.
объяснение
Эта программа состоит из двух циклов. Первый вычисляет факториал ввода, другой разбивает результат на его цифры и складывает их вместе. Затем сумма печатается, и программа заканчивается.
Начало
Сначала нам нужно подготовить стек. Для этой части мы используем первые три инструкции. IP начинается на четвертой строке, указывая на восток. Стек пуст.
. . .
. . .
. . .
0 1 I . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .
Мы будем хранить сумму в самом низу стека, поэтому нам нужно начинать с 0
суммы, храня ее в нижней части стека. Затем нам нужно нажать a 1
, потому что ввод будет сначала умножен на число перед ним. Если бы это было ноль, факториал также всегда давал бы ноль. Наконец, мы читаем входные данные как целое число.
Теперь, стек [0, 1, input]
и IP находится на четвертой строке, четвертом столбце, указывающем на восток.
Факториальная петля
Это простой цикл, который умножает два верхних элемента стека (результат предыдущего цикла и входные данные - n, а затем уменьшает входные данные. Он прерывается, когда ввод достигает 0. Из-за $
инструкции IP пропускает u
- Поворот. Цикл является следующей частью куба. IP начинается в четвертой строке, четвертом столбце.
u * .
$ s .
! ( .
. . . ^ < . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . .
. . .
. . .
Из-за этого ^
персонажа IP сразу начинает двигаться на север. Затем u
поворачивает IP и перемещает его вправо. Внизу есть еще одна стрелка: <
указывает IP обратно в ^
. Стек начинается как [previousresult, input-n]
, где n
число итераций. В цикле выполняются следующие символы:
*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]
Затем в верхней части стека (уменьшил вход) сверяется 0
по !
инструкции, и если это 0
, тоu
персонаж будет пропущен.
Суммируйте цифры
IP оборачивается вокруг куба, заканчиваясь на последнем символе в четвертой строке, первоначально указывая на запад. Следующий цикл состоит в основном из всех оставшихся символов:
. . .
. . .
. . .
. . . . . W % N W ! ; <
, ; ; q + p @ O p u s .
. . . . . . . . . . . .
. . .
. . .
. . .
Цикл сначала удаляет верхний элемент из стека (который либо либо, 10
либо 0
), а затем проверяет, что осталось от результата факториала. Если это было уменьшено до 0
, печатается дно стека (сумма), и программа останавливается. В противном случае выполняются следующие инструкции (стек начинается как [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]
И цикл начинается снова, пока не будет factorial/10
равен 0.
n>21