Special factorials: Difference between revisions
m (→{{header|FreeBASIC}}: -rm stray thing) |
m (→{{header|Phix}}: added syntax colouring the hard way) |
||
Line 440: | Line 440: | ||
which means sf/H/af/ef aren't usable independently as-is, but reconstitution should be easy enough |
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). |
(along with somewhat saner and thread-safe routine-local vars). |
||
<lang Phix> |
<!--<lang Phix>--> |
||
<span style="color: #008080;">include</span> <span style="color: #7060A8;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
mpz {r,fn} = mpz_inits(2) -- res, scratch var |
|||
<span style="color: #7060A8;">mpz</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- res, scratch var</span> |
|||
procedure sf(integer i) |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">sf</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_fac_ui(fn, i) |
|||
<span style="color: #7060A8;">mpz_fac_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_mul(r,r,fn) |
|||
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
procedure H(integer i) |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">H</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_ui_pow_ui(fn, i, i) |
|||
<span style="color: #7060A8;">mpz_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_mul(r,r,fn) |
|||
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
integer sgn = 0 |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">sgn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
procedure af(integer i) |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">af</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_fac_ui(fn, i) |
|||
<span style="color: #7060A8;">mpz_fac_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_mul_si(fn,fn,sgn) |
|||
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sgn</span><span style="color: #0000FF;">)</span> |
|||
sgn *= -1 |
|||
<span style="color: #000000;">sgn</span> <span style="color: #0000FF;">*=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> |
|||
mpz_add(r,r,fn) |
|||
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
procedure ef(integer i) |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">ef</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
integer e = mpz_get_integer(r) |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> |
|||
mpz_set_si(r,i) |
|||
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> |
|||
mpz_pow_ui(r, r, e) |
|||
<span style="color: #7060A8;">mpz_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">)</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
procedure test(string fmt, integer fn, init=1, m=9) |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">init</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> |
|||
sequence res = {} |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for n=0 to m do |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">m</span> <span style="color: #008080;">do</span> |
|||
mpz_set_si(r,init) |
|||
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">init</span><span style="color: #0000FF;">)</span> |
|||
sgn = iff(and_bits(n,1)?1:-1) -- (af only) |
|||
<span style="color: #000000;">sgn</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (af only)</span> |
|||
for i=1 to n do |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span> |
|||
fn(i) -- or papply(tagset(n),fn) |
|||
<span style="color: #000000;">fn</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- or papply(tagset(n),fn)</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
res = append(res,mpz_get_str(r)) |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">))</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
printf(1,fmt,{join(res)}) |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)})</span> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
test("First 10 superfactorials: %s\n",sf) |
|||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"First 10 superfactorials: %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sf</span><span style="color: #0000FF;">)</span> |
|||
test("First 10 hyperfactorials: %s\n",H) |
|||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"First 10 hyperfactorials: %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">H</span><span style="color: #0000FF;">)</span> |
|||
test("First 10 alternating factorials: %s\n",af,0) |
|||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"First 10 alternating factorials: %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">af</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> |
|||
test("First 5 exponential factorials: %s\n",ef,1,4) |
|||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"First 5 exponential factorials: %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ef</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span> |
|||
ef(5) -- (nb now only works because ef(4) was just called) |
|||
<span style="color: #000000;">ef</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (nb now only works because ef(4) was just called)</span> |
|||
printf(1,"Number of digits in 5$: %,d\n",mpz_sizeinbase(r,10)) |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Number of digits in 5$: %,d\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">mpz_sizeinbase</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">))</span> |
|||
function rf(integer n) |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">rf</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
|||
if n=1 then return "0" end if |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"0"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
integer fac = 1, i = 1 |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fac</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
while fac<n do |
|||
<span style="color: #008080;">while</span> <span style="color: #000000;">fac</span><span style="color: #0000FF;"><</span><span style="color: #000000;">n</span> <span style="color: #008080;">do</span> |
|||
fac *= i |
|||
<span style="color: #000000;">fac</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">i</span> |
|||
if fac=n then return sprint(i) end if |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">fac</span><span style="color: #0000FF;">=</span><span style="color: #000000;">n</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
i += 1 |
|||
<span style="color: #000000;">i</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
end while |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
return "undefined" |
|||
<span style="color: #008080;">return</span> <span style="color: #008000;">"undefined"</span> |
|||
end function |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
printf(1,"Reverse factorials: %s\n",{join(apply({1,2,6,24,120,720,5040,40320,362880,3628800,119},rf))})</lang> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Reverse factorials: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">apply</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">24</span><span style="color: #0000FF;">,</span><span style="color: #000000;">120</span><span style="color: #0000FF;">,</span><span style="color: #000000;">720</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5040</span><span style="color: #0000FF;">,</span><span style="color: #000000;">40320</span><span style="color: #0000FF;">,</span><span style="color: #000000;">362880</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3628800</span><span style="color: #0000FF;">,</span><span style="color: #000000;">119</span><span style="color: #0000FF;">},</span><span style="color: #000000;">rf</span><span style="color: #0000FF;">))})</span> |
|||
<!--</lang>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Revision as of 22:55, 30 March 2021
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
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
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).
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
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)