Special factorials
This task is an aggregation of lesser-known factorials that nevertheless have some mathematical use.
Name | Formula | Example calculation | Links |
---|---|---|---|
Superfactorial | n sf(n) = ∏ k! k=1 |
sf(4) = 1! × 2! × 3! × 4! = 288 | |
Hyperfactorial | n H(n) = ∏ kk k=1 |
H(4) = 11 × 22 × 33 × 44 = 27,648 | |
Alternating factorial | n af(n) = ∑ (-1)n-ii! i=1 |
af(3) = -12×1! + -11×2! + -10×3! = 5 | |
Exponential factorial | n$ = n(n-1)(n-2)... | 4$ = 4321 = 262,144 |
- Task
- Write a function/procedure/routine for each of the factorials in the table above.
- Show sf(n), H(n), and af(n) where 0 ≤ n ≤ 9. Only show as many numbers as the data types in your language can handle. Bignums are welcome, but not required.
- Show 0$, 1$, 2$, 3$, and 4$.
- Show the number of digits in 5$. (Optional)
- Write a function/procedure/routine to find the inverse factorial (sometimes called reverse factorial). That is, if 5! = 120, then rf(120) = 5. This function is simply undefined for most inputs.
- Use the inverse factorial function to show the inverse factorials of 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, and 3628800.
- Show rf(119). The result should be undefined.
- Notes
- Since the factorial inverse of 1 is both 0 and 1, your function should return 0 in this case since it is normal to use the first match found in a series.
- See also
- Factorial
- Factorions
- Left factorials
- Multifactorial
- Primorial numbers
- Stirling numbers of the first kind
C
<lang c>#include <math.h>
- include <stdint.h>
- include <stdio.h>
/* n! = 1 * 2 * 3 * ... * n */ uint64_t factorial(int n) {
uint64_t result = 1; int i;
for (i = 1; i <= n; i++) { result *= i; }
return result;
}
/* if(n!) = n */ int inverse_factorial(uint64_t f) {
int p = 1; int i = 1;
if (f == 1) { return 0; }
while (p < f) { p *= i; i++; }
if (p == f) { return i - 1; } return -1;
}
/* sf(n) = 1! * 2! * 3! * ... . n! */ uint64_t super_factorial(int n) {
uint64_t result = 1; int i;
for (i = 1; i <= n; i++) { result *= factorial(i); }
return result;
}
/* H(n) = 1^1 * 2^2 * 3^3 * ... * n^n */ uint64_t hyper_factorial(int n) {
uint64_t result = 1; int i;
for (i = 1; i <= n; i++) { result *= (uint64_t)powl(i, i); }
return result;
}
/* af(n) = -1^(n-1)*1! + -1^(n-2)*2! + ... + -1^(0)*n! */ uint64_t alternating_factorial(int n) {
uint64_t result = 0; int i;
for (i = 1; i <= n; i++) { if ((n - i) % 2 == 0) { result += factorial(i); } else { result -= factorial(i); } }
return result;
}
/* n$ = n ^ (n - 1) ^ ... ^ (2) ^ 1 */ uint64_t exponential_factorial(int n) {
uint64_t result = 0; int i;
for (i = 1; i <= n; i++) { result = (uint64_t)powl(i, (long double)result); }
return result;
}
void test_factorial(int count, uint64_t(*func)(int), char *name) {
int i;
printf("First %d %s:\n", count, name); for (i = 0; i < count ; i++) { printf("%llu ", func(i)); } printf("\n");
}
void test_inverse(uint64_t f) {
int n = inverse_factorial(f); if (n < 0) { printf("rf(%llu) = No Solution\n", f); } else { printf("rf(%llu) = %d\n", f, n); }
}
int main() {
int i;
/* cannot display the 10th result correctly */ test_factorial(9, super_factorial, "super factorials"); printf("\n");
/* cannot display the 9th result correctly */ test_factorial(8, super_factorial, "hyper factorials"); printf("\n");
test_factorial(10, alternating_factorial, "alternating factorials"); printf("\n");
test_factorial(5, exponential_factorial, "exponential factorials"); printf("\n");
test_inverse(1); test_inverse(2); test_inverse(6); test_inverse(24); test_inverse(120); test_inverse(720); test_inverse(5040); test_inverse(40320); test_inverse(362880); test_inverse(3628800); test_inverse(119);
return 0;
}</lang>
- Output:
First 9 super factorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 First 8 hyper factorials: 1 1 2 12 288 34560 24883200 125411328000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 0 1 2 9 262144 rf(1) = 0 rf(2) = 2 rf(6) = 3 rf(24) = 4 rf(120) = 5 rf(720) = 6 rf(5040) = 7 rf(40320) = 8 rf(362880) = 9 rf(3628800) = 10 rf(119) = No Solution
C++
<lang cpp>#include <cmath>
- include <cstdint>
- include <iostream>
- include <functional>
/* n! = 1 * 2 * 3 * ... * n */ uint64_t factorial(int n) {
uint64_t result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result;
}
/* if(n!) = n */ int inverse_factorial(uint64_t f) {
int p = 1; int i = 1;
if (f == 1) { return 0; }
while (p < f) { p *= i; i++; }
if (p == f) { return i - 1; } return -1;
}
/* sf(n) = 1! * 2! * 3! * ... . n! */ uint64_t super_factorial(int n) {
uint64_t result = 1; for (int i = 1; i <= n; i++) { result *= factorial(i); } return result;
}
/* H(n) = 1^1 * 2^2 * 3^3 * ... * n^n */ uint64_t hyper_factorial(int n) {
uint64_t result = 1; for (int i = 1; i <= n; i++) { result *= (uint64_t)powl(i, i); } return result;
}
/* af(n) = -1^(n-1)*1! + -1^(n-2)*2! + ... + -1^(0)*n! */ uint64_t alternating_factorial(int n) {
uint64_t result = 0; for (int i = 1; i <= n; i++) { if ((n - i) % 2 == 0) { result += factorial(i); } else { result -= factorial(i); } } return result;
}
/* n$ = n ^ (n - 1) ^ ... ^ (2) ^ 1 */ uint64_t exponential_factorial(int n) {
uint64_t result = 0; for (int i = 1; i <= n; i++) { result = (uint64_t)powl(i, (long double)result); } return result;
}
void test_factorial(int count, std::function<uint64_t(int)> func, const std::string &name) {
std::cout << "First " << count << ' ' << name << '\n'; for (int i = 0; i < count; i++) { std::cout << func(i) << ' '; } std::cout << '\n';
}
void test_inverse(uint64_t f) {
int n = inverse_factorial(f); if (n < 0) { std::cout << "rf(" << f << ") = No Solution\n"; } else { std::cout << "rf(" << f << ") = " << n << '\n'; }
}
int main() {
/* cannot display the 10th result correctly */ test_factorial(9, super_factorial, "super factorials"); std::cout << '\n';
/* cannot display the 9th result correctly */ test_factorial(8, hyper_factorial, "hyper factorials"); std::cout << '\n';
test_factorial(10, alternating_factorial, "alternating factorials"); std::cout << '\n';
test_factorial(5, exponential_factorial, "exponential factorials"); std::cout << '\n';
test_inverse(1); test_inverse(2); test_inverse(6); test_inverse(24); test_inverse(120); test_inverse(720); test_inverse(5040); test_inverse(40320); test_inverse(362880); test_inverse(3628800); test_inverse(119);
return 0;
}</lang>
- Output:
First 9 super factorials 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 First 8 hyper factorials 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 First 10 alternating factorials 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials 0 1 2 9 262144 rf(1) = 0 rf(2) = 2 rf(6) = 3 rf(24) = 4 rf(120) = 5 rf(720) = 6 rf(5040) = 7 rf(40320) = 8 rf(362880) = 9 rf(3628800) = 10 rf(119) = No Solution
Factor
<lang factor>USING: formatting io kernel math math.factorials math.functions math.parser math.ranges prettyprint sequences sequences.extras ; IN: rosetta-code.special-factorials
- sf ( n -- m ) [1..b] [ n! ] map-product ;
- (H) ( n -- m ) [1..b] [ dup ^ ] map-product ;
- H ( n -- m ) [ 1 ] [ (H) ] if-zero ;
- af ( n -- m ) n [1..b] [| i | -1 n i - ^ i n! * ] map-sum ;
- $ ( n -- m ) [1..b] [ ] [ swap ^ ] map-reduce ;
- (rf) ( n -- m )
[ 1 1 ] dip [ dup reach > ] [ [ 1 + [ * ] keep ] dip ] while swapd = swap and ;
- rf ( n -- m ) dup 1 = [ drop 0 ] [ (rf) ] if ;
- .show ( n quot -- )
[ pprint bl ] compose each-integer nl ; inline
"First 10 superfactorials:" print 10 [ sf ] .show nl
"First 10 hyperfactorials:" print 10 [ H ] .show nl
"First 10 alternating factorials:" print 10 [ af ] .show nl
"First 5 exponential factorials:" print 5 [ $ ] .show nl
"Number of digits in 5$:" print 5 $ log10 >integer 1 + . nl
{ 1 2 6 24 120 720 5040 40320 362880 3628800 119 } [ dup rf "rf(%d) = %u\n" printf ] each nl</lang>
- Output:
First 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 0 1 2 9 262144 Number of digits in 5$: 183231 rf(1) = 0 rf(2) = 2 rf(6) = 3 rf(24) = 4 rf(120) = 5 rf(720) = 6 rf(5040) = 7 rf(40320) = 8 rf(362880) = 9 rf(3628800) = 10 rf(119) = f
Fermat
<lang>Function Sf(n) = Prod<k=1, n>[k!].
Function H(n) = Prod<k=1, n>[k^k].
Function Af(n) = Sigma<i=1,n>[(-1)^(n-i)i!].
Function Ef(n) = if n < 2 then 1 else n^Ef(n-1) fi.
Function Rf(n) =
for r = 1 to n do rr:=r!; if rr=n then Return(r) fi; if rr>n then Return(-1) fi; od.
for n=0 to 9 do !!(Sf(n), H(n), Af(n)) od; !!' '; for n=0 to 4 do !!Ef(n) od; !!' '; for n=1 to 10 do !!Rf(n!) od; !!Rf(119)</lang>
FreeBASIC
Only goes up to H(7) due to overflow. Using a library with big int support is possible, but would only add bloat without being illustrative. <lang freebasic>function factorial(n as uinteger) as ulongint
if n<2 then return 1 else return n*factorial(n-1)
end function
function sf(n as uinteger) as ulongint
dim as ulongint p=1 for k as uinteger = 1 to n p*=factorial(k) next k return p
end function
function H( n as uinteger ) as ulongint
dim as ulongint p=1 for k as uinteger = 1 to n p*=k^k next k return p
end function
function af( n as uinteger ) as longint
dim as longint s=0 for i as uinteger = 1 to n s += (-1)^(n-i)*factorial(i) next i return s
end function
function ef( n as uinteger ) as ulongint
if n<2 then return 1 else return n^ef(n-1)
end function
function rf( n as ulongint ) as integer
dim as uinteger r=0,rr while true rr=factorial(r) if rr>n then return -1 if rr=n then return r r+=1 wend
end function
for n as uinteger = 0 to 7
print sf(n), H(n), af(n)
next n print for n as uinteger = 0 to 4
print ef(n);" ";
next n print : print for n as uinteger =0 to 9
print rf(factorial(n));" ";
next n print rf(119)</lang>
Go
<lang go>package main
import (
"fmt" "math/big"
)
func sf(n int) *big.Int {
if n < 2 { return big.NewInt(1) } sfact := big.NewInt(1) fact := big.NewInt(1) for i := 2; i <= n; i++ { fact.Mul(fact, big.NewInt(int64(i))) sfact.Mul(sfact, fact) } return sfact
}
func H(n int) *big.Int {
if n < 2 { return big.NewInt(1) } hfact := big.NewInt(1) for i := 2; i <= n; i++ { bi := big.NewInt(int64(i)) hfact.Mul(hfact, bi.Exp(bi, bi, nil)) } return hfact
}
func af(n int) *big.Int {
if n < 1 { return new(big.Int) } afact := new(big.Int) fact := big.NewInt(1) sign := new(big.Int) if n%2 == 0 { sign.SetInt64(-1) } else { sign.SetInt64(1) } t := new(big.Int) for i := 1; i <= n; i++ { fact.Mul(fact, big.NewInt(int64(i))) afact.Add(afact, t.Mul(fact, sign)) sign.Neg(sign) } return afact
}
func ef(n int) *big.Int {
if n < 1 { return big.NewInt(1) } t := big.NewInt(int64(n)) return t.Exp(t, ef(n-1), nil)
}
func rf(n *big.Int) int {
i := 0 fact := big.NewInt(1) for { if fact.Cmp(n) == 0 { return i } if fact.Cmp(n) > 0 { return -1 } i++ fact.Mul(fact, big.NewInt(int64(i))) }
}
func main() {
fmt.Println("First 10 superfactorials:") for i := 0; i < 10; i++ { fmt.Println(sf(i)) }
fmt.Println("\nFirst 10 hyperfactorials:") for i := 0; i < 10; i++ { fmt.Println(H(i)) }
fmt.Println("\nFirst 10 alternating factorials:") for i := 0; i < 10; i++ { fmt.Print(af(i), " ") }
fmt.Println("\n\nFirst 5 exponential factorials:") for i := 0; i <= 4; i++ { fmt.Print(ef(i), " ") }
fmt.Println("\n\nThe number of digits in 5$ is", len(ef(5).String()))
fmt.Println("\nReverse factorials:") facts := []int64{1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 119} for _, fact := range facts { bfact := big.NewInt(fact) rfact := rf(bfact) srfact := fmt.Sprintf("%d", rfact) if rfact == -1 { srfact = "none" } fmt.Printf("%4s <- rf(%d)\n", srfact, fact) }
}</lang>
- Output:
First 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 1 1 2 9 262144 The number of digits in 5$ is 183231 Reverse factorials: 0 <- rf(1) 2 <- rf(2) 3 <- rf(6) 4 <- rf(24) 5 <- rf(120) 6 <- rf(720) 7 <- rf(5040) 8 <- rf(40320) 9 <- rf(362880) 10 <- rf(3628800) none <- rf(119)
Julia
No recursion. <lang julia>superfactorial(n) = n < 1 ? 1 : mapreduce(factorial, *, 1:n) sf(n) = superfactorial(n)
hyperfactorial(n) = n < 1 ? 1 : mapreduce(i -> i^i, *, 1:n) H(n) = hyperfactorial(n)
alternating_factorial(n) = n < 1 ? 0 : mapreduce(i -> (-1)^(n - i) * factorial(i), +, 1:n) af(n) = alternating_factorial(n)
exponential_factorial(n) = n < 1 ? 1 : foldl((x, y) -> y^x, 1:n) n$(n) = exponential_factorial(n)
function reverse_factorial(n)
n == 1 && return 0 fac = one(n) for i in 2:10000 fac *= i fac == n && return i fac > n && break end return nothing
end rf(n) = reverse_factorial(n)
println("N Superfactorial Hyperfactorial", " "^18, "Alternating Factorial Exponential Factorial\n", "-"^98) for n in 0:9
print(n, " ") for f in [sf, H, af, n$] if n < 5 || f != n$ print(rpad(f(Int128(n)), f == H ? 37 : 24)) end end println()
end
println("\nThe number of digits in n$(5) is ", length(string(n$(BigInt(5)))))
println("\n\nN Reverse Factorial\n", "-"^25) for n in [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 119]
println(rpad(n, 10), rf(n))
end
</lang>
- Output:
N Superfactorial Hyperfactorial Alternating Factorial Exponential Factorial -------------------------------------------------------------------------------------------------- 0 1 1 0 1 1 1 1 1 1 2 2 4 1 2 3 12 108 5 9 4 288 27648 19 262144 5 34560 86400000 101 6 24883200 4031078400000 619 7 125411328000 3319766398771200000 4421 8 5056584744960000 55696437941726556979200000 35899 9 1834933472251084800000 21577941222941856209168026828800000 326981 The number of digits in n$(5) is 183231 N Reverse Factorial ------------------------- 1 0 2 2 6 3 24 4 120 5 720 6 5040 7 40320 8 362880 9 3628800 10 119 nothing
Kotlin
<lang scala>import java.math.BigInteger import java.util.function.Function
/* n! = 1 * 2 * 3 * ... * n */ fun factorial(n: Int): BigInteger {
val bn = BigInteger.valueOf(n.toLong()) var result = BigInteger.ONE var i = BigInteger.TWO while (i <= bn) { result *= i++ } return result
}
/* if(n!) = n */ fun inverseFactorial(f: BigInteger): Int {
if (f == BigInteger.ONE) { return 0 }
var p = BigInteger.ONE var i = BigInteger.ONE
while (p < f) { p *= i++ }
if (p == f) { return i.toInt() - 1 } return -1
}
/* sf(n) = 1! * 2! * 3! * ... . n! */ fun superFactorial(n: Int): BigInteger {
var result = BigInteger.ONE for (i in 1..n) { result *= factorial(i) } return result
}
/* H(n) = 1^1 * 2^2 * 3^3 * ... * n^n */ fun hyperFactorial(n: Int): BigInteger {
var result = BigInteger.ONE for (i in 1..n) { val bi = BigInteger.valueOf(i.toLong()) result *= bi.pow(i) } return result
}
/* af(n) = -1^(n-1)*1! + -1^(n-2)*2! + ... + -1^(0)*n! */ fun alternatingFactorial(n: Int): BigInteger {
var result = BigInteger.ZERO for (i in 1..n) { if ((n - i) % 2 == 0) { result += factorial(i) } else { result -= factorial(i) } } return result
}
/* n$ = n ^ (n - 1) ^ ... ^ (2) ^ 1 */ fun exponentialFactorial(n: Int): BigInteger {
var result = BigInteger.ZERO for (i in 1..n) { result = BigInteger.valueOf(i.toLong()).pow(result.toInt()) } return result
}
fun testFactorial(count: Int, f: Function<Int, BigInteger>, name: String) {
println("First $count $name:") for (i in 0 until count) { print("${f.apply(i)} ") } println()
}
fun testInverse(f: Long) {
val n = inverseFactorial(BigInteger.valueOf(f)) if (n < 0) { println("rf($f) = No Solution") } else { println("rf($f) = $n") }
}
fun main() {
testFactorial(10, ::superFactorial, "super factorials") println()
testFactorial(10, ::hyperFactorial, "hyper factorials") println()
testFactorial(10, ::alternatingFactorial, "alternating factorials") println()
testFactorial(5, ::exponentialFactorial, "exponential factorials") println()
testInverse(1) testInverse(2) testInverse(6) testInverse(24) testInverse(120) testInverse(720) testInverse(5040) testInverse(40320) testInverse(362880) testInverse(3628800) testInverse(119)
}</lang>
- Output:
First 10 super factorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyper factorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 0 1 2 9 262144 rf(1) = 0 rf(2) = 2 rf(6) = 3 rf(24) = 4 rf(120) = 5 rf(720) = 6 rf(5040) = 7 rf(40320) = 8 rf(362880) = 9 rf(3628800) = 10 rf(119) = No Solution
Lua
<lang lua>-- n! = 1 * 2 * 3 * ... * n-1 * n function factorial(n)
local result = 1 local i = 1 while i <= n do result = result * i i = i + 1 end return result
end
-- if(n!) = n function inverse_factorial(f)
local p = 1 local i = 1
if f == 1 then return 0 end
while p < f do p = p * i i = i + 1 end
if p == f then return i - 1 end return -1
end
-- sf(n) = 1! * 2! * 3! * ... * (n-1)! * n! function super_factorial(n)
local result = 1 local i = 1 while i <= n do result = result * factorial(i) i = i + 1 end return result
end
-- H(n) = 1^1 * 2^2 * 3^3 * ... * (n-1)^(n-1) * n^n function hyper_factorial(n)
local result = 1 for i=1, n do result = result * i ^ i end return result
end
-- af(n) = -1^(n-1)*1! + -1^(n-1)*2! + ... + -1^(1)*(n-1)! + -1^(0)*n! function alternating_factorial(n)
local result = 0 for i=1, n do if (n - i) % 2 == 0 then result = result + factorial(i) else result = result - factorial(i) end end return result
end
-- n$ = n ^ (n-1) ^ ... ^ 2 ^ 1 function exponential_factorial(n)
local result = 0 for i=1, n do result = i ^ result end return result
end
function test_factorial(count, f, name)
print("First " .. count .. " " .. name) for i=1,count do io.write(math.floor(f(i - 1)) .. " ") end print() print()
end
function test_inverse(f)
local n = inverse_factorial(f) if n < 0 then print("rf(" .. f .. " = No Solution") else print("rf(" .. f .. " = " .. n) end
end
test_factorial(9, super_factorial, "super factorials") test_factorial(8, hyper_factorial, "hyper factorials") test_factorial(10, alternating_factorial, "alternating factorials") test_factorial(5, exponential_factorial, "exponential factorials")
test_inverse(1) test_inverse(2) test_inverse(6) test_inverse(24) test_inverse(120) test_inverse(720) test_inverse(5040) test_inverse(40320) test_inverse(362880) test_inverse(3628800) test_inverse(119)</lang>
- Output:
First 9 super factorials 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 First 8 hyper factorials 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 First 10 alternating factorials 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials 0 1 2 9 262144 rf(1 = 0 rf(2 = 2 rf(6 = 3 rf(24 = 4 rf(120 = 5 rf(720 = 6 rf(5040 = 7 rf(40320 = 8 rf(362880 = 9 rf(3628800 = 10 rf(119 = No Solution
Nim
<lang Nim>import math, strformat, strutils, sugar import bignum
proc pow(a: int; n: Int): Int =
## Compute a^n for "n" big integer. var n = n var a = newInt(a) if a > 0: result = newInt(1) # Start with Int values for "n". while not n.isZero: if (n and 1) != 0: result *= a n = n shr 1 a *= a
func sf(n: Natural): Int =
result = newInt(1) for i in 2..n: result *= fac(i)
func hf(n: Natural): Int =
result = newInt(1) for i in 2..n: result *= pow(i, uint(i))
func af(n: Natural): Int =
result = newInt(0) var m = (n and 1) shl 1 - 1 for i in 1..n: result += m * fac(i) m = -m
func ef(n: Natural): Int =
result = newInt(1) for k in 2..n: result = pow(k, result)
func rf(n: int | Int): int =
if n == 1: return 0 result = 1 var p = newInt(1) while p < n: inc result p *= result if p > n: result = -1
let sfs = collect(newSeq, for n in 0..9: sf(n)) echo &"First {sfs.len} superfactorials: ", sfs.join(" ")
let hfs = collect(newSeq, for n in 0..9: hf(n)) echo &"First {hfs.len} hyperfactorials: ", hfs.join(" ")
let afs = collect(newSeq, for n in 0..9: af(n)) echo &"First {afs.len} alternating factorials: ", afs.join(" ")
let efs = collect(newSeq, for n in 0..4: ef(n)) echo &"First {efs.len} exponential factorials: ", efs.join(" ")
echo "\nNumber of digits of ef(5): ", len($ef(5))
echo "\nReverse factorials:" for n in [1, 2, 6, 24, 119, 120, 720, 5040, 40320, 362880, 3628800]:
let r = rf(n) echo &"{n:7}: ", if r >= 0: &"{r:2}" else: "undefined"</lang>
- Output:
First 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 1 1 2 9 262144 Number of digits of ef(5): 183231 Reverse factorials: 1: 0 2: 2 6: 3 24: 4 119: undefined 120: 5 720: 6 5040: 7 40320: 8 362880: 9 3628800: 10
Perl
<lang perl>use strict; use warnings; use feature qw<signatures say>; no warnings qw<experimental::signatures>; use bigint try => 'GMP'; use ntheory qw<vecprod vecsum vecreduce vecfirstidx>;
sub f ($n) { vecreduce { $a * $b } 1, 1..$n } sub sf ($n) { vecprod map { f($_) } 1..$n } sub H ($n) { vecprod map { $_ ** $_ } 1..$n } sub af ($n) { vecsum map { (-1) ** ($n-$_) * f($_) } 1..$n } sub ef ($n) { vecreduce { $b ** $a } 1..$n } sub rf ($n) {
my $v = vecfirstidx { f($_) >= $n } 0..1E6; $n == f($v) ? $v : 'Nope'
}
say 'sf : ' . join ' ', map { sf $_ } 0..9; say 'H : ' . join ' ', map { H $_ } 0..9; say 'af : ' . join ' ', map { af $_ } 0..9; say 'ef : ' . join ' ', map { ef $_ } 1..4; say '5$ has ' . length(5**4**3**2) . ' digits'; say 'rf : ' . join ' ', map { rf $_ } <1 2 6 24 120 720 5040 40320 362880 3628800>; say 'rf(119) = ' . rf(119);</lang>
- Output:
sf : 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 H : 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 af : 0 1 1 5 19 101 619 4421 35899 326981 ef : 1 2 9 262144 5$ has 183231 digits rf : 0 2 3 4 5 6 7 8 9 10 rf(119) = Nope
Phix
Rather than leave this as four somewhat disjoint tasks with quite a bit of repetition, I commoned-up init/loop/print into test(), which means sf/H/af/ef aren't usable independently as-is, but reconstitution should be easy enough (along with somewhat saner and thread-safe routine-local vars).
with javascript_semantics include mpfr.e mpz {r,fn} = mpz_inits(2) -- res, scratch var procedure sf(integer i) mpz_fac_ui(fn, i) mpz_mul(r,r,fn) end procedure procedure H(integer i) mpz_ui_pow_ui(fn, i, i) mpz_mul(r,r,fn) end procedure integer sgn = 0 procedure af(integer i) mpz_fac_ui(fn, i) mpz_mul_si(fn,fn,sgn) sgn *= -1 mpz_add(r,r,fn) end procedure procedure ef(integer i) integer e = mpz_get_integer(r) mpz_set_si(r,i) mpz_pow_ui(r, r, e) end procedure procedure test(string fmt, integer fn, init=1, m=9) sequence res = {} for n=0 to m do mpz_set_si(r,init) sgn = iff(and_bits(n,1)?1:-1) -- (af only) for i=1 to n do fn(i) -- or papply(tagset(n),fn) end for res = append(res,mpz_get_str(r)) end for printf(1,fmt,{join(res)}) end procedure test("First 10 superfactorials: %s\n",sf) test("First 10 hyperfactorials: %s\n",H) test("First 10 alternating factorials: %s\n",af,0) test("First 5 exponential factorials: %s\n",ef,1,4) ef(5) -- (nb now only works because ef(4) was just called) printf(1,"Number of digits in 5$: %,d\n",mpz_sizeinbase(r,10)) function rf(integer n) if n=1 then return "0" end if integer fac = 1, i = 1 while fac<n do fac *= i if fac=n then return sprint(i) end if i += 1 end while return "undefined" end function printf(1,"Reverse factorials: %s\n",{join(apply({1,2,6,24,120,720,5040,40320,362880,3628800,119},rf))})
- Output:
First 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 1 1 2 9 262144 Number of digits in 5$: 183,231 Reverse factorials: 0 2 3 4 5 6 7 8 9 10 undefined
Raku
<lang perl6>sub postfix:<!> ($n) { [*] 1 .. $n } sub postfix:<$> ($n) { [R**] 1 .. $n }
sub sf ($n) { [*] map { $_! }, 1 .. $n } sub H ($n) { [*] map { $_ ** $_ }, 1 .. $n } sub af ($n) { [+] map { (-1) ** ($n - $_) * $_! }, 1 .. $n } sub rf ($n) {
state @f = 1, |[\*] 1..*; $n == .value ?? .key !! Nil given @f.first: :p, * >= $n;
}
say 'sf : ', map &sf , 0..9; say 'H : ', map &H , 0..9; say 'af : ', map &af , 0..9; say '$ : ', map *$ , 1..4;
say '5$ has ', 5$.chars, ' digits';
say 'rf : ', map &rf, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800; say 'rf(119) = ', rf(119).raku;</lang>
- Output:
sf : (1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000) H : (1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000) af : (0 1 1 5 19 101 619 4421 35899 326981) $ : (1 2 9 262144) 5$ has 183231 digits rf : (0 2 3 4 5 6 7 8 9 10) rf(119) = Nil
REXX
<lang rexx>/*REXX program to compute some special factorials: superfactorials, hyperfactorials,*/ /*───────────────────────────────────── alternating factorials, exponential factorials.*/ numeric digits 100 /*allows humongous results to be shown.*/ call hdr 'super'; do j=0 to 9; $= $ sf(j); end; call tell call hdr 'hyper'; do j=0 to 9; $= $ hf(j); end; call tell call hdr 'alternating '; do j=0 to 9; $= $ af(j); end; call tell call hdr 'exponential '; do j=0 to 5; $= $ ef(j); end; call tell
@= 'the number of decimal digits in the exponential factorial of '
say @ 5 " is:"; $= ' 'commas( efn( ef(5) ) ); call tell
@= 'the inverse factorial of' do j=1 for 10; say @ right(!(j), 8) " is: " rf(!(j)) end /*j*/ say @ right(119, 8) " is: " rf(119)
exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ !: procedure; parse arg x; != 1; do #=2 to x; != ! * #; end; return ! af: procedure; parse arg x; if x==0 then return 0; prev= 0; call af!; return ! af!: do #=1 for x; != !(#) - prev; prev= !; end; return ! commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ? ef: procedure; parse arg x; if x==0 | x==1 then return 1; return x**ef(x-1) efn: procedure; parse arg x; numeric digits 9; x= x; parse var x 'E' d; return d+1 sf: procedure; parse arg x; != 1; do #=2 to x; != ! * !(#); end; return ! hf: procedure; parse arg x; != 1; do #=2 to x; != ! * #**#; end; return ! rf: procedure; parse arg x; do #=0 until f>=x; f=!(#); end; return rfr() rfr: if x==f then return #; ?= 'undefined'; return ? hdr: parse arg ?,,$; say 'the first ten '?"factorials:"; return tell: say substr($, 2); say; $=; return</lang>
- output when using the internal default input:
the first 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 the first 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 the first 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 the first 5 exponential factorials: 1 1 2 9 262144 the number of decimal digits in the exponential factorial of 5 is: 183,231 the inverse factorial of 1 is: 0 the inverse factorial of 2 is: 2 the inverse factorial of 6 is: 3 the inverse factorial of 24 is: 4 the inverse factorial of 120 is: 5 the inverse factorial of 720 is: 6 the inverse factorial of 5040 is: 7 the inverse factorial of 40320 is: 8 the inverse factorial of 362880 is: 9 the inverse factorial of 3628800 is: 10 the inverse factorial of 119 is: undefined
Seed7
<lang seed7>$ include "seed7_05.s7i";
include "bigint.s7i";
const func bigInteger: superfactorial (in bigInteger: limit) is func
result var bigInteger: product is 1_; local var bigInteger: k is 0_; begin for k range 1_ to limit do product *:= !k; # prefix ! calculates the factorial in Seed7 end for; end func;
const func bigInteger: hyperfactorial (in bigInteger: limit) is func
result var bigInteger: product is 1_; local var bigInteger: k is 0_; begin for k range 1_ to limit do product *:= k ** ord(k); end for; end func;
const func bigInteger: alternating (in bigInteger: limit) is func
result var bigInteger: sum is 0_; local var bigInteger: i is 0_; begin for i range 1_ to limit do sum +:= (-1_) ** ord(limit - i) * !i; end for; end func;
const func bigInteger: exponential (in bigInteger: limit) is func
result var bigInteger: pow is 0_; local var bigInteger: n is 0_; begin for n range 1_ to limit do pow := n ** ord(pow); end for; end func;
const func integer: invFactorial (in integer: n) is func
result var integer: r is 0; local var integer: a is 1; var integer: b is 1; begin if n <> 1 then while n > a do incr(b); a *:= b; end while; if a = n then r := b; else r := -1; end if; end if; end func;
const proc: show (in bigInteger: limit, inout bigInteger: aVariable,
ref func bigInteger: anExpression) is func
begin for aVariable range 0_ to limit do write(anExpression <& " "); end for; writeln; writeln; end func;
const proc: main is func
local var bigInteger: x is 0_; var integer: n is 0; begin writeln("First 10 superfactorials:"); show(9_, x, superfactorial(x)); writeln("First 10 hyperfactorials:"); show(9_, x, hyperfactorial(x)); writeln("First 10 alternating factorials:"); show(9_, x, alternating(x)); writeln("First 5 exponential factorials:"); show(4_, x, exponential(x)); for n range [] (1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 119) do writeln("invFactorial(" <& n <& ") = " <& invFactorial(n)); end for; end func;</lang>
- Output:
First 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 0 1 2 9 262144 invFactorial(1) = 0 invFactorial(2) = 2 invFactorial(6) = 3 invFactorial(24) = 4 invFactorial(120) = 5 invFactorial(720) = 6 invFactorial(5040) = 7 invFactorial(40320) = 8 invFactorial(362880) = 9 invFactorial(3628800) = 10 invFactorial(119) = -1
Wren
We've little choice but to use BigInt here as Wren can only deal natively with integers up to 2^53. <lang ecmascript>import "/big" for BigInt import "/fmt" for Fmt
var sf = Fn.new { |n|
if (n < 2) return BigInt.one var sfact = BigInt.one var fact = BigInt.one for (i in 2..n) { fact = fact * i sfact = sfact * fact } return sfact
}
var H = Fn.new { |n|
if (n < 2) return BigInt.one var hfact = BigInt.one for (i in 2..n) hfact = hfact * BigInt.new(i).pow(i) return hfact
}
var af = Fn.new { |n|
if (n < 1) return BigInt.zero var afact = BigInt.zero var fact = BigInt.one var sign = (n%2 == 0) ? -1 : 1 for (i in 1..n) { fact = fact * i afact = afact + fact * sign sign = -sign } return afact
}
var ef // recursive ef = Fn.new { |n|
if (n < 1) return BigInt.one return BigInt.new(n).pow(ef.call(n-1))
}
var rf = Fn.new { |n|
var i = 0 var fact = BigInt.one while (true) { if (fact == n) return i if (fact > n) return "none" i = i + 1 fact = fact * i }
}
System.print("First 10 superfactorials:") for (i in 0..9) System.print(sf.call(i))
System.print("\nFirst 10 hyperfactorials:") for (i in 0..9) System.print(H.call(i))
System.print("\nFirst 10 alternating factorials:") for (i in 0..9) System.write("%(af.call(i)) ")
System.print("\n\nFirst 5 exponential factorials:") for (i in 0..4) System.write("%(ef.call(i)) ") System.print()
Fmt.print("\nThe number of digits in 5$$ is $,d\n", ef.call(5).toString.count)
System.print("Reverse factorials:") var facts = [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 119] for (fact in facts) Fmt.print("$4s <- rf($d)", rf.call(fact), fact)</lang>
- Output:
First 10 superfactorials: 1 1 2 12 288 34560 24883200 125411328000 5056584744960000 1834933472251084800000 First 10 hyperfactorials: 1 1 4 108 27648 86400000 4031078400000 3319766398771200000 55696437941726556979200000 21577941222941856209168026828800000 First 10 alternating factorials: 0 1 1 5 19 101 619 4421 35899 326981 First 5 exponential factorials: 1 1 2 9 262144 The number of digits in 5$ is 183,231 Reverse factorials: 0 <- rf(1) 2 <- rf(2) 3 <- rf(6) 4 <- rf(24) 5 <- rf(120) 6 <- rf(720) 7 <- rf(5040) 8 <- rf(40320) 9 <- rf(362880) 10 <- rf(3628800) none <- rf(119)