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.
- See also
- Factorial
- Factorions
- Left factorials
- Multifactorial
- Primorial numbers
- Stirling numbers of the first kind
Factor
<lang factor>USING: formatting io kernel math math.factorials math.functions math.parser math.ranges prettyprint sequences sequences.extras ;
- 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 ;
- .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) = 1 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
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 ? -1 : 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)
for i in 1:100000 fac = factorial(typeof(n)(i)) fac == n && return i fac > n && break end return nothing
end rf(n) = reverse_factorial(n)
println("N Superfactorial Hyperfactorial Alternating Factorial Exponential Factorial\n", "-"^88) for n in 0:9
print(n, " ") for f in [sf, H, af, n$] if n < 5 || f != n$ print(rpad((f(n)), 25)) 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 -1 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 -907465429310504960 35899 9 8705808953839190016 2649120435010011136 326981 The number of digits in n$(5) is 183231 N Reverse Factorial ------------------------- 1 1 2 2 6 3 24 4 120 5 720 6 5040 7 40320 8 362880 9 3628800 10 119 nothing
REXX
<lang rexx>/*REXX program to compute some special factorials: superfactorials, hyperfactorials,*/ /*───────────────────────────────────── alternating factorials, exponential factorials.*/ numeric digits 100 /*allow humonous numbers to be computed*/ parse arg LO HI nef xef nrf xrf /*obtain optional arguments from the CL*/ if LO== | LO=="," then LO= 0 /*Not specified? Then use the default.*/ if HI== | HI=="," then HI= 9 /* " " " " " " */ if nef== | nef=="," then nef= 5 /* " " " " " " */ if xef== | xef=="," then xef= nef /* " " " " " " */ if nrf== | nrf=="," then nrf= 10 /* " " " " " " */ if nef== | nef=="," then nef= 5 /* " " " " " " */ if xrf== | xrf=="," then xrf= 119 /* " " " " " " */ num= HI-LO+1 /*calculate the # of numbers to be used*/ call hdr num, 'super'; do j=LO to HI; $= $ sf(j); end; call tell call hdr num, 'hyper'; do j=LO to HI; $= $ hf(j); end; call tell call hdr num, 'alternating '; do j=LO to HI; $= $ af(j); end; call tell call hdr nef, 'exponential '; do j=0 for nef; $= $ ef(j); end; call tell
@= 'the number of decimal digits in the exponential factorial of '
say @ xef " is:"; $= ' 'commas( efn( ef( xef) ) ); call tell
@= 'the inverse factorial of ' do j=1 for nrf; fp= !(j); say @ fp " is: " rf(fp) end /*j*/ say @ xrf " is: " rf(xrf)
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; 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 ! hdr: parse arg nn,what,,$; say 'the first ' nn " "what'factorials:'; return tell: say substr($, 2); say; $=; return /*──────────────────────────────────────────────────────────────────────────────────────*/ rf: procedure; parse arg x,u; do #=0 until f>x; f=!(#); if x==f then return #; end
return 'undefined'</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
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 f = Fn.new { |n|
if (n < 2) return BigInt.one var fact = BigInt.one for (i in 2..n) fact = fact * i return fact
}
var sf = Fn.new { |n|
if (n < 2) return BigInt.one var sfact = BigInt.one for (i in 2..n) sfact = sfact * f.call(i) 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 sign = (n%2 == 0) ? -1 : 1 for (i in 1..n) { afact = afact + f.call(i) * 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 while (true) { var fact = f.call(i) if (fact == n) return i if (fact > n) return "none" i = i + 1 }
}
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)