36
\$\begingroup\$

Not to be confused with Find the factorial!

Introduction

The factorial of an integer n can be calculated by $$n!=n\times(n-1)\times(n-2)\times(...)\times2\times1$$

This is relatively easy and nothing new. However, factorials can be extended to double factorials, such that $$n!!=n\times(n-2)\times(n-4)\times(...)\times4\times2$$ for even numbers, and $$n!!=n\times(n-2)\times(n-4)\times(...)\times3\times1$$ for odd numbers. But we're not limited to double factorials. For example $$n!!!=n\times(n-3)\times(n-6)\times(...)\times6\times3$$ or $$n!!!=n\times(n-3)\times(n-6)\times(...)\times5\times2$$ or $$n!!!=n\times(n-3)\times(n-6)\times(...)\times4\times1$$ depending on the starting value.

In summary: $${\displaystyle n!^{(k)}={\begin{cases}1&{\text{if }}n=0 \\n&{\text{if }}0<n\leq k\\n\cdot\left({(n-k)!}^{(k)}\right)&{\text{if }}n>k\end{cases}}}$$ where $${\displaystyle n!^{(k)}=n\underbrace{!\dots!}_{k}}$$ Or, in plain English: Subtract the factorial count from the base number repeatedly and multiply all resulting positive integers.

The Challenge

Write a function that will calculate any kind of repeated factorial for any non-negative integer.

Input

Either

  • A string containing a non-negative base-ten integer, followed by 1 or more exclamation marks. E.g. "6!" or "9!!" or "40!!!!!!!!!!!!!!!!!!!!".

or

  • The same values represented by two integers: one non-negative base value and one positive value representing the factorial count. This can be done according to any format from the default I/O rules.

Output

The result of said calculation.

Challenge remarks

  • 0! equals 1 by definition. Your code must account for this.
  • The factorial count is limited by $$ 0 < factorial~count \leq base~value $$outside this range, you are free to output whatever. Aside from 0!, which is the only exception to this rule.

Examples

Input                              Output

3!!!                               3
0!                                 1
6!                                 720
9!!                                945
10!!!!!!!!                         20
40!!!!!!!!!!!!!!!!!!!!             800
420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  41697106428257280000000000000000

Try it with an ungolfed Python implementation: Try it online!

General remarks

\$\endgroup\$
8
  • 6
    \$\begingroup\$ The examples list 0! but the challenge remarks say that the factorial count will be less than or equal to the base value. \$\endgroup\$ Aug 5 '19 at 13:09
  • 1
    \$\begingroup\$ Wouldn't 3!!! be zero? n*(n-3) = 3*(3-3) = 0. \$\endgroup\$
    – ouflak
    Aug 5 '19 at 13:31
  • 2
    \$\begingroup\$ @ouflak If it works like 1!, not really. It's more like 1! = 1. 2!! = 2. 3!!! = 3. There's no calculation, because you are at the end of the recursiveness. No 0 in products or else every single factorial would drop down to 0 in the end. \$\endgroup\$ Aug 5 '19 at 14:16
  • 4
    \$\begingroup\$ 3!!!!!!! should not be undefined—it should just yield the answer 3. It's the same as 1!!=1 (not undefined). Also your input specification says that there will always be at least one !, so the first example 3 doesn't fit the specification. \$\endgroup\$ Aug 5 '19 at 18:04
  • 3
    \$\begingroup\$ @FabianRöling: But that's not what this is. It's not (3!)! instead it's removing terms from a factorial. It's a misleading name; I came in assuming it was going to be applying the Factorial function repeatedly in a chain and had to read carefully to see what it actually was. Fortunately the question does explain it clearly. A better name might be stride factorial or step factorial or something. \$\endgroup\$ Aug 8 '19 at 5:31

36 Answers 36

1
2
1
\$\begingroup\$

Gaia, 6 bytes

…)¦v%Π

Try it online!

Takes input as n, k, so input of 3 4 would be 3!!!!.

…	 push [0...n-1], or [] if n == 0
 )¦	 increment each value (does nothing if [])
   v	 reverse list
    %	 take every k'th element
     Π	 product; product([]) = 1.
\$\endgroup\$
1
\$\begingroup\$

Bash + coreutils, 27

seq -s\* $[$1+!$1] -$2 1|bc

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PHP, 47 bytes

Recursive function with tests

function f($n,$c){return$n>0?f($n-$c,$c)*$n:1;}

Try it online!


PHP, 54 bytes

Loop version (original answer)

for($n=$argv[1],$f=1;$n>0;$f*=$n,$n-=$argv[2]);echo$f;

Try it online!


First argument is the the base value and second one is the factorial count.

Supports specified valid range, but outputs big numbers in scientific notation. For example the last sample is shown as 4.1697106428257E+31.

\$\endgroup\$
1
\$\begingroup\$

Lua, 150 145 129 bytes

i=io.read()p,c=i.gsub(i,"!","")p=p+0
function f(n,c)r=1 if n~=0 then
while(n>0) do r=r*n n=n-c
end
end
return r end
print(f(p,c))

Try it online!

Ported from Charlie's ArnoldC psuedocode. -16 bytes thanks to Charlie

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can submit only the function as answer, which can also be improved. \$\endgroup\$
    – Charlie
    Aug 6 '19 at 17:13
  • \$\begingroup\$ @Charlie, Yeah when I get more comfy with the idea of headers and footers in TIO, I'll experiment a bit more. \$\endgroup\$
    – ouflak
    Aug 7 '19 at 6:32
1
\$\begingroup\$

Python 3 (Input as string), 82 bytes

m=lambda n,s:n<1or n*m(n-s,s)
f=lambda x:int(m(int(x.split("!")[0]),x.count("!")))

Try it online!

Note: the outer int() in f is solely for the fact that without it, 0! will output True

\$\endgroup\$
1
  • \$\begingroup\$ Nice approach! True == 1 in Python, so without conversion it is still valid. \$\endgroup\$
    – Jitse
    Aug 8 '19 at 5:35
1
+400
\$\begingroup\$

Factor + math.unicode, 30 29 24 bytes

  • Saved 1 byte thanks to @Bubbler
  • Saved 5 bytes thanks to @chunes!
[ 1 rot neg <range> Π ]

Try it online!

Takes k (which -th factorial) and then n. First we push an n onto the stack, then rot makes the stack look like n 1 k. neg negates k, which will act as the step for a range from n to 1 (made using <range>). Then Π finds the product of that range, and that's it.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ If you take the arguments in k n order, you can do 1 rot neg instead of neg 1 swap to save a byte. \$\endgroup\$
    – Bubbler
    Mar 29 at 23:19
  • 1
    \$\begingroup\$ You can save 5 bytes with Π from math.unicode instead of product. \$\endgroup\$
    – chunes
    Mar 30 at 0:26
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.