Yup, 3333 31 29 bytes
*{{:0e-}-0]~]~{~|~|0~--e~}0~--#\~#\}1#0e#
node yup.js -l "*{{:0e-}-0]~]~{~|~|0~--e~}0~--#\~#\}1#"0e#" -n <input>
λ node yup.js -l "*{{:0e-}-0]~]~{~|~|0~--e~}0~--#\~#\}1#"0e#" -n 5
120
λ node yup.js examples\factorial.yup -n 0
1
*{{:0e-}]~{~|~|0~--e~}~#\}0e#
* ` take input
{ } ` while TOS -- if zero, we advance to the }
0e# ` print number 1 (exp(0))
` otherwise (nonzero)
{ } ` while TOS is not zero
: ` duplicate TOS
0 ` push 0
e ` pop 0, push exp(0) = 1
- ` subtract 1
` we eventually are at zero.
] ` we move that zero to the bottom of the stack
~ ` switch top two for looping offset
{~ ~} ` while STOS
|~|0~--e ` multiply two elements (see further down)
~ ` switch the top zero with the result
# ` print the result
\ ` exit program (so we don't print the final one)
Multiplication
To comeIn this program, I have multiplication defined as thus:
|~|0~--e
First, observe 0~--
. This pushes a zero behind the TOS, and subtracts twice:
command | stack
| a b
0 | a b 0
~ | a 0 b
- | a (-b)
- | a - (-b) = a + b
This performs addition. Let's replace 0~--
with +
for clarity:
|~|+e
Now, |
is ln
. So watch the stack:
command | stack
| a b
| | a ln(b)
~ | ln(b) a
| | ln(b) ln(a)
+ | (ln(b)+ln(a))
e | exp(ln(b)+ln(a))
And, by the theorem of logarithms, this is multiplication.