Combinations and permutations: Difference between revisions
(I could not find this specific C & P task in RC, hence this draft...) |
(Add Lua implementation) |
||
(128 intermediate revisions by 56 users not shown) | |||
Line 1: | Line 1: | ||
{{ |
{{task|Probability and statistics}} |
||
{{wikipedia|Combination |
{{wikipedia|Combination}} |
||
Implement a Combination <sup>n</sup>C<sub>k</sub> and Permutation <sup>n</sup>P<sub>k</sub> Operators in the target language: |
|||
{{wikipedia|Permutation}} |
|||
* <math> ^nC_k =\binom nk = \frac{n(n-1)\ldots(n-k+1)}{k(k-1)\dots1} </math> |
|||
* <math>^nP_k = n\cdot(n-1)\cdot(n-2)\cdots(n-k+1)</math> |
|||
c.f. Wikipedia for a full explanation. |
|||
;Task: |
|||
'''To test, generate examples of:''' |
|||
Implement the [[wp:Combination|combination]] <big> (<sup>n</sup>C<sub>k</sub>) </big> and [[wp:Permutation|permutation]] <big> (<sup>n</sup>P<sub>k</sub>) </big> operators in the target language: |
|||
* Permutations from 1 to 12 and Combinations from 10 to 60 using Integer arithmetic. |
|||
* Permutations from 5 to 15000 and Combinations from 100 to 1000 using Floating point arithmetic. |
|||
:::* <math>^n\operatorname C_k =\binom nk = \frac{n(n-1)\ldots(n-k+1)}{k(k-1)\dots1} </math> |
|||
:::* <math>^n\operatorname P_k = n\cdot(n-1)\cdot(n-2)\cdots(n-k+1)</math> |
|||
<br> |
|||
See the Wikipedia articles for a more detailed description. |
|||
'''To test''', generate and print examples of: |
|||
* A sample of permutations from 1 to 12 and Combinations from 10 to 60 using exact Integer arithmetic. |
|||
* A sample of permutations from 5 to 15000 and Combinations from 100 to 1000 using approximate Floating point arithmetic.<br> This 'floating point' code could be implemented using an approximation, e.g., by calling the [[Gamma function]]. |
|||
;Related task: |
|||
* [[Evaluate binomial coefficients]] |
|||
{{Template:Combinations and permutations}} |
|||
<br><br> |
|||
=={{header|11l}}== |
|||
{{trans|C++}} |
|||
<syntaxhighlight lang="11l">F perm(=n, p) |
|||
BigInt r = 1 |
|||
V k = n - p |
|||
L n > k |
|||
r *= n-- |
|||
R r |
|||
F comb(n, =k) |
|||
V r = perm(n, k) |
|||
L k > 0 |
|||
r I/= k-- |
|||
R r |
|||
L(i) 1..11 |
|||
print(‘P(12,’i‘) = ’perm(12, i)) |
|||
L(i) (10.<60).step(10) |
|||
print(‘C(60,’i‘) = ’comb(60, i))</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
P(12,1) = 12 |
|||
P(12,2) = 132 |
|||
P(12,3) = 1320 |
|||
P(12,4) = 11880 |
|||
P(12,5) = 95040 |
|||
P(12,6) = 665280 |
|||
P(12,7) = 3991680 |
|||
P(12,8) = 19958400 |
|||
P(12,9) = 79833600 |
|||
P(12,10) = 239500800 |
|||
P(12,11) = 479001600 |
|||
C(60,10) = 75394027566 |
|||
C(60,20) = 4191844505805495 |
|||
C(60,30) = 118264581564861424 |
|||
C(60,40) = 4191844505805495 |
|||
C(60,50) = 75394027566 |
|||
</pre> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
Line 14: | Line 70: | ||
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.6 algol68g-2.6].}} |
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.6 algol68g-2.6].}} |
||
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}} |
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}} |
||
'''File: prelude_combinations_and_permutations.a68'''< |
'''File: prelude_combinations_and_permutations.a68'''<syntaxhighlight lang="algol68"># -*- coding: utf-8 -*- # |
||
COMMENT REQUIRED by "prelude_combinations_and_permutations.a68" CO |
|||
CO REQUIRES |
|||
MODE CPINT = #LONG# |
MODE CPINT = #LONG# ~; |
||
MODE CPOUT = #LONG# |
MODE CPOUT = #LONG# ~; # the answer, can be REAL # |
||
MODE CPREAL = |
MODE CPREAL = ~; # the answer, can be REAL # |
||
PROC cp fix value error = (#REF# CPARGS args)BOOL: ~; |
|||
#PROVIDES:# |
|||
PROC cp fix value error = (#REF# CPARGS args)BOOL: ... |
|||
# OP C = (CP~,CP~)CP~: ~ # |
|||
END CO |
|||
# OP P = (CP~,CP~)CP~: ~ # |
|||
END COMMENT |
|||
MODE CPARGS = STRUCT(CHAR name, #REF# CPINT n,k); |
|||
PRIO C = 8, P = 8; # should be 7.5, a priority between *,/ and **,SHL,SHR etc # |
PRIO C = 8, P = 8; # should be 7.5, a priority between *,/ and **,SHL,SHR etc # |
||
Line 31: | Line 91: | ||
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("P",n,r)) THEN stop FI FI; |
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("P",n,r)) THEN stop FI FI; |
||
CPOUT out := 1; |
CPOUT out := 1; |
||
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r |
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r)! # |
||
FOR i FROM n-r+1 TO n DO out *:= i OD; |
FOR i FROM n-r+1 TO n DO out *:= i OD; |
||
out |
out |
||
); |
); |
||
OP P = (CPREAL n, r)CPREAL: # 'ln gamma' requires GSL library # |
|||
# A real version, a better way (probably) would be to use the gamma function # |
|||
exp(ln gamma(n+1)-ln gamma(n-r+1)); |
|||
OP P = (CPREAL n, r)CPREAL: ( |
|||
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r)! # |
|||
COMMENT # alternate slower version # |
|||
OP P = (CPREAL n, r)CPREAL: ( # alternate slower version # |
|||
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("P",ENTIER n,ENTIER r)) THEN stop FI FI; |
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("P",ENTIER n,ENTIER r)) THEN stop FI FI; |
||
CPREAL out := 1; |
CPREAL out := 1; |
||
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r |
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r)! # |
||
CPREAL i := n-r+1; |
CPREAL i := n-r+1; |
||
WHILE i <= n DO |
WHILE i <= n DO |
||
Line 50: | Line 114: | ||
out |
out |
||
); |
); |
||
END COMMENT |
|||
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! # |
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! # |
||
Line 60: | Line 125: | ||
FOR larger fact FROM largest+1 TO n DO |
FOR larger fact FROM largest+1 TO n DO |
||
# try and prevent overflow, p.s. there must be a smarter way to do this # |
# try and prevent overflow, p.s. there must be a smarter way to do this # |
||
# Problems: loop stalls when 'smaller fact' is a largeish co prime # |
|||
out *:= larger fact; |
out *:= larger fact; |
||
WHILE smaller fact <= smallest ANDF out MOD smaller fact = 0 DO |
WHILE smaller fact <= smallest ANDF out MOD smaller fact = 0 DO |
||
Line 69: | Line 135: | ||
); |
); |
||
OP C = (CPREAL n, CPREAL r)CPREAL: # 'ln gamma' requires GSL library # |
|||
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! # |
|||
exp(ln gamma(n+1)-ln gamma(n-r+1)-ln gamma(r+1)); |
|||
CO does not prevent overflow! |
|||
OP C = (CPREAL n, r)CPREAL: ( |
|||
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("C", ENTIER n,ENTIER r)) THEN stop FI FI; |
|||
n P r / ( r P r ) |
|||
); |
|||
END CO |
|||
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! # |
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! # |
||
COMMENT # alternate slower version # |
|||
OP C = (CPREAL n, r)CPREAL: ( |
|||
OP C = (CPREAL n, REAL r)CPREAL: ( |
|||
IF n < r ORF r < 0 THEN IF NOT cp fix value error(("C",ENTIER n,ENTIER r)) THEN stop FI FI; |
IF n < r ORF r < 0 THEN IF NOT cp fix value error(("C",ENTIER n,ENTIER r)) THEN stop FI FI; |
||
CPREAL largest = ( r > n - r | r | n - r ); |
CPREAL largest = ( r > n - r | r | n - r ); |
||
Line 85: | Line 147: | ||
REAL smaller fact := 2; |
REAL smaller fact := 2; |
||
REAL larger fact := largest+1; |
REAL larger fact := largest+1; |
||
WHILE larger fact <= n DO # todo: check |
WHILE larger fact <= n DO # todo: check underflow here # |
||
# try and prevent overflow, p.s. there must be a smarter way to do this # |
# try and prevent overflow, p.s. there must be a smarter way to do this # |
||
out *:= larger fact; |
out *:= larger fact; |
||
Line 96: | Line 158: | ||
out # EXIT with: n P r OVER r P r # |
out # EXIT with: n P r OVER r P r # |
||
); |
); |
||
END COMMENT |
|||
SKIP</ |
SKIP</syntaxhighlight>'''File: test_combinations_and_permutations.a68'''<syntaxhighlight lang="algol68">#!/usr/bin/a68g --script # |
||
# -*- coding: utf-8 -*- # |
# -*- coding: utf-8 -*- # |
||
Line 104: | Line 167: | ||
MODE CPOUT = #LONG# INT; # the answer, can be REAL # |
MODE CPOUT = #LONG# INT; # the answer, can be REAL # |
||
MODE CPREAL = REAL; # the answer, can be REAL # |
MODE CPREAL = REAL; # the answer, can be REAL # |
||
MODE CPARGS = STRUCT(CHAR name, #REF# CPINT n,k); |
|||
PROC cp fix value error = (#REF# CPARGS args)BOOL: ( |
PROC cp fix value error = (#REF# CPARGS args)BOOL: ( |
||
putf(stand error, ($"Value error: "g(0)gg(0)"arg out of range"l$, |
putf(stand error, ($"Value error: "g(0)gg(0)"arg out of range"l$, |
||
Line 110: | Line 172: | ||
FALSE # unfixable # |
FALSE # unfixable # |
||
); |
); |
||
#PROVIDES:# |
|||
# OP C = (CP~,CP~)CP~: ~ # |
|||
# OP P = (CP~,CP~)CP~: ~ # |
|||
PR READ "prelude_combinations_and_permutations.a68" PR; |
PR READ "prelude_combinations_and_permutations.a68" PR; |
||
Line 137: | Line 202: | ||
OD; |
OD; |
||
printf($l"A sample of Combinations from |
printf($l"A sample of Combinations from 10 to 190:"l$); |
||
FOR i FROM 100 BY 100 TO 1000 DO |
FOR i FROM 100 BY 100 TO 1000 DO |
||
REAL r = i, |
REAL r = i, |
||
Line 144: | Line 209: | ||
printf(($"("g(0)" C "g(0)") = "g(0,1)$, r, first, r C first, $", "$)); |
printf(($"("g(0)" C "g(0)") = "g(0,1)$, r, first, r C first, $", "$)); |
||
printf(($"("g(0)" C "g(0)") = "g(0,1)$, r, second, r C second, $l$)) |
printf(($"("g(0)" C "g(0)") = "g(0,1)$, r, second, r C second, $l$)) |
||
OD</ |
OD</syntaxhighlight>'''Output:''' |
||
<pre> |
<pre> |
||
A sample of Permutations from 1 to 12: |
A sample of Permutations from 1 to 12: |
||
Line 182: | Line 247: | ||
145 P 143 = 4.02396303e251, 145 P 133 = 1.68014597e243 |
145 P 143 = 4.02396303e251, 145 P 133 = 1.68014597e243 |
||
A sample of Combinations from 10 to 190: |
|||
(100 C 98) = 4950.0, (100 C 90) = 17310309456438.8 |
|||
(200 C 198) = 19900.0, (200 C 186) = 1179791641436960000000.0 |
|||
(300 C 298) = 44850.0, (300 C 283) = 2287708142022840000000000000.0 |
|||
(400 C 398) = 79800.0, (400 C 380) = 2788360983670300000000000000000000.0 |
|||
(500 C 498) = 124750.0, (500 C 478) = 132736424690773000000000000000000000000.0 |
|||
(600 C 598) = 179700.0, (600 C 576) = 4791686682467800000000000000000000000000000.0 |
|||
(700 C 698) = 244650.0, (700 C 674) = 145478651313640000000000000000000000000000000000.0 |
|||
(800 C 798) = 319600.0, (800 C 772) = 3933526871034430000000000000000000000000000000000000.0 |
|||
(900 C 898) = 404550.0, (900 C 870) = 98033481673646900000000000000000000000000000000000000000.0 |
|||
(1000 C 998) = 499500.0, (1000 C 969) = 76023224077705100000000000000000000000000000000000000000000.0 |
|||
</pre> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="arturo">printPermutations: function [s,b][ |
|||
print [ |
|||
"P(" ++ (to :string s) ++ ", " ++ (to :string b) ++ ") = " |
|||
permutate.count.by:b @1..s |
|||
] |
|||
] |
|||
printCombinations: function [s,b][ |
|||
print [ |
|||
"C(" ++ (to :string s) ++ ", " ++ (to :string b) ++ ") = " |
|||
combine.count.by:b @1..s |
|||
] |
|||
] |
|||
printPermutations 4 2 |
|||
printPermutations 5 3 |
|||
printPermutations 6 4 |
|||
printPermutations 7 5 |
|||
printPermutations 8 6 |
|||
printPermutations 9 7 |
|||
printPermutations 10 8 |
|||
printPermutations 11 9 |
|||
printPermutations 12 10 |
|||
printCombinations 10 8 |
|||
printCombinations 20 18 |
|||
printCombinations 30 28 |
|||
printCombinations 40 38 |
|||
printCombinations 50 48 |
|||
printCombinations 60 58 |
|||
printPermutations 340 230 |
|||
printPermutations 12503 150 |
|||
printCombinations 180 40 |
|||
printCombinations 970 730 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>P(4, 2) = 12 |
|||
P(5, 3) = 60 |
|||
P(6, 4) = 360 |
|||
P(7, 5) = 2520 |
|||
P(8, 6) = 20160 |
|||
P(9, 7) = 181440 |
|||
P(10, 8) = 1814400 |
|||
P(11, 9) = 19958400 |
|||
P(12, 10) = 239500800 |
|||
C(10, 8) = 45 |
|||
C(20, 18) = 190 |
|||
C(30, 28) = 435 |
|||
C(40, 38) = 780 |
|||
C(50, 48) = 1225 |
|||
C(60, 58) = 1770 |
|||
P(340, 230) = 321163468667018390278490855166116943643915115883733627394541858241858716874364895663708654024956544433526906929220370657178037367849691887585605027786348781323683175128970012088045935740649918420588744620257725216845699632806302776510600871474726786041782200035955935929612857643030896557053167285732409630111804341546261862735713347179073784452257244336775041366281305006608295780372754879670614948719662927123558774623452956076264437724405141046975318837351290035912604435611648000000000000000000000000000000000000000000000000000000000 |
|||
P(12503, 150) = 145349029342353586631193854127379263889050707122840603258866143765734805000836318095430535878283222399986691383724192776832431401841845807936456562635873483263903741650446537273646795588914347285406358840689987529465482210964310466322364415189531610901593861947474126246323721536314280740814336769614384426370056684232165925069433834623283158338231715677812329656785966269970444585319639178491261742879187758508103438009278190651455732354378754778290406101258502700133885808094777181331499601845451634234055547273229226095279158651885556410705696845808314349918299242931159040000000000000000000000000000000000000000 |
|||
C(180, 40) = 18290112128130495302949953479795255876590 |
|||
C(970, 730) = 1460703798049835817371501066063364773159305309662093793682805325059313312798468600051903640905890411826065678898559485932184945661085268182815842989416642105002033447941384758262043195945021701492825484266010877073654424416642736902160</pre> |
|||
=={{header|Bracmat}}== |
|||
This solution shows results from bignum as well as floating point implementations. If bignum answers are very big, only the first 50 digits and a count of the digits that are not shown are shown. The bignum answers are shown as Cn and Pn, while the floating point answers are shown as Cf and Pf. Answers are aligned to make it easy to compare the decimals. |
|||
<syntaxhighlight lang="bracmat"> ( C |
|||
= n k coef |
|||
. !arg:(?n,?k) |
|||
& (!n+-1*!k:<!k:?k|) |
|||
& 1:?coef |
|||
& whl |
|||
' ( !k:>0 |
|||
& !coef*!n*!k^-1:?coef |
|||
& !k+-1:?k |
|||
& !n+-1:?n |
|||
) |
|||
& !coef |
|||
) |
|||
& ( compileBinomialFunctionThatDoesFloatingPointCalculations |
|||
= |
|||
. new |
|||
$ ( UFP |
|||
, |
|||
' ( (s.n) (s.k) |
|||
. "************************************************************** |
|||
*** Notice the difference between the following four lines *** |
|||
*** of code and the much shorter (!n+-1*!k:<!k:?k|) in *** |
|||
*** function C above. UFP grammar is simpler than usual *** |
|||
*** Bracmat grammar. UFP code is therefore less terse. *** |
|||
**************************************************************" |
|||
& !n+-1*!k:?n-k |
|||
& ( !n-k:<!k&!n-k:?k |
|||
| |
|||
) |
|||
& 1:?coef |
|||
& whl |
|||
' ( !k:>0 |
|||
& !coef*!n*!k^-1:?coef |
|||
& !k+-1:?k |
|||
& !n+-1:?n |
|||
) |
|||
& !coef |
|||
) |
|||
) |
|||
) |
|||
& compileBinomialFunctionThatDoesFloatingPointCalculations$ |
|||
: ?binom |
|||
& ( P |
|||
= n k result |
|||
. !arg:(?n,?k) |
|||
& !n+-1*!k:?k |
|||
& 1:?result |
|||
& whl |
|||
' ( !n:>!k |
|||
& !n*!result:?result |
|||
& !n+-1:?n |
|||
) |
|||
& !result |
|||
) |
|||
& ( compilePermutationFunctionThatDoesFloatingPointCalculations |
|||
= |
|||
. new |
|||
$ ( UFP |
|||
, |
|||
' ( (s.n) (s.k) |
|||
. !n+-1*!k:?k |
|||
& 1:?result |
|||
& whl |
|||
' ( !n:>!k |
|||
& !n*!result:?result |
|||
& !n+-1:?n |
|||
) |
|||
& !result |
|||
) |
|||
) |
|||
) |
|||
& compilePermutationFunctionThatDoesFloatingPointCalculations$ |
|||
: ?permu |
|||
& 0:?i |
|||
& whl |
|||
' ( 1+!i:~>12:?i |
|||
& div$(!i.3):?k |
|||
& out$(!i P !k "=" P$(!i,!k)) |
|||
) |
|||
& 0:?i |
|||
& whl |
|||
' ( 10+!i:~>60:?i |
|||
& div$(!i.3):?k |
|||
& out$(!i Cn !k "= " C$(!i,!k)) |
|||
& out$(!i Cf !k "=" (binom..go)$(!i,!k)) |
|||
) |
|||
& ( displayBig |
|||
= |
|||
. @(!arg:?show [50 ? [?length) |
|||
& !show "... (" !length+-50 " more digits)" |
|||
| !arg |
|||
) |
|||
& 5 50 500 1000 5000 15000:?is |
|||
& whl |
|||
' ( !is:%?i ?is |
|||
& div$(!i.3):?k |
|||
& out |
|||
$ ( str |
|||
$ (!i " Pn " !k " = " displayBig$(P$(!i,!k))) |
|||
) |
|||
& out |
|||
$ ( str |
|||
$ (!i " Pf " !k " = " (permu..go)$(!i,!k)) |
|||
) |
|||
) |
|||
& 0:?i |
|||
& whl |
|||
' ( 100+!i:~>1000:?i |
|||
& div$(!i.3):?k |
|||
& out |
|||
$ ( str |
|||
$ (!i " Cn " !k " = " displayBig$(C$(!i,!k))) |
|||
) |
|||
& out |
|||
$ ( str |
|||
$ (!i " Cf " !k " = " (binom..go)$(!i,!k)) |
|||
) |
|||
) |
|||
& all done;</syntaxhighlight> |
|||
Output: |
|||
<pre>1 P 0 = 1 |
|||
2 P 0 = 1 |
|||
3 P 1 = 3 |
|||
4 P 1 = 4 |
|||
5 P 1 = 5 |
|||
6 P 2 = 30 |
|||
7 P 2 = 42 |
|||
8 P 2 = 56 |
|||
9 P 3 = 504 |
|||
10 P 3 = 720 |
|||
11 P 3 = 990 |
|||
12 P 4 = 11880 |
|||
10 Cn 3 = 120 |
|||
10 Cf 3 = 1.1999999999999999E+02 |
|||
20 Cn 6 = 38760 |
|||
20 Cf 6 = 3.8759999999999993E+04 |
|||
30 Cn 10 = 30045015 |
|||
30 Cf 10 = 3.0045014999999989E+07 |
|||
40 Cn 13 = 12033222880 |
|||
40 Cf 13 = 1.2033222880000000E+10 |
|||
50 Cn 16 = 4923689695575 |
|||
50 Cf 16 = 4.9236896955750000E+12 |
|||
60 Cn 20 = 4191844505805495 |
|||
60 Cf 20 = 4.1918445058054930E+15 |
|||
5 Pn 1 = 5 |
|||
5 Pf 1 = 5.0000000000000000E+00 |
|||
50 Pn 16 = 103017324974226408345600000 |
|||
50 Pf 16 = 1.0301732497422640E+26 |
|||
500 Pn 166 = 35348749217429427876093618266017623068440028791060... (385 more digits) |
|||
500 Pf 166 = INF |
|||
1000 Pn 333 = 59693262885034150890397017659007842809981894765670... (922 more digits) |
|||
1000 Pf 333 = INF |
|||
5000 Pn 1666 = 68567457572556742754845369402488960622341567102448... (5976 more digits) |
|||
5000 Pf 1666 = INF |
|||
15000 Pn 5000 = 96498539887274939220148588059312959807922816886808... (20420 more digits) |
|||
15000 Pf 5000 = INF |
|||
100 Cn 33 = 294692427022540894366527900 |
|||
100 Cf 33 = 2.9469242702254079E+26 |
|||
200 Cn 66 = 72697525451692783415270666511927389767550269141935... (4 more digits) |
|||
200 Cf 66 = 7.2697525451692816E+53 |
|||
300 Cn 100 = 41582514632585647447833835263264055802804660057436... (32 more digits) |
|||
300 Cf 100 = 4.1582514632585569E+81 |
|||
400 Cn 133 = 12579486841821087021333484756519650044917494358375... (60 more digits) |
|||
400 Cf 133 = 1.2579486841821091E+109 |
|||
500 Cn 166 = 39260283861944227552204083450723314281973490135301... (87 more digits) |
|||
500 Cf 166 = 3.9260283861944195E+136 |
|||
600 Cn 200 = 25060177832214028050056167705132288352025510250879... (115 more digits) |
|||
600 Cf 200 = 2.5060177832213946E+164 |
|||
700 Cn 233 = 81032035633395999047404536440311382329449203119421... (142 more digits) |
|||
700 Cf 233 = 8.1032035633395859E+191 |
|||
800 Cn 266 = 26456233626836270342888292995561242550915240450150... (170 more digits) |
|||
800 Cf 266 = 2.6456233626836295E+219 |
|||
900 Cn 300 = 17433563732964466429607307650857183476303419689548... (198 more digits) |
|||
900 Cf 300 = 1.7433563732964451E+247 |
|||
1000 Cn 333 = 57761345531476516697774863235496017223394580195002... (225 more digits) |
|||
1000 Cf 333 = 5.7761345531476355E+274 |
|||
{!} all done</pre> |
|||
=={{header|C}}== |
|||
Using big integers. GMP in fact has a factorial function which is quite possibly more efficient, though using it would make code longer. |
|||
<syntaxhighlight lang="c">#include <gmp.h> |
|||
void perm(mpz_t out, int n, int k) |
|||
{ |
|||
mpz_set_ui(out, 1); |
|||
k = n - k; |
|||
while (n > k) mpz_mul_ui(out, out, n--); |
|||
} |
|||
void comb(mpz_t out, int n, int k) |
|||
{ |
|||
perm(out, n, k); |
|||
while (k) mpz_divexact_ui(out, out, k--); |
|||
} |
|||
int main(void) |
|||
{ |
|||
mpz_t x; |
|||
mpz_init(x); |
|||
perm(x, 1000, 969); |
|||
gmp_printf("P(1000,969) = %Zd\n", x); |
|||
comb(x, 1000, 969); |
|||
gmp_printf("C(1000,969) = %Zd\n", x); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
=={{header|C#}}== |
|||
{{trans|Java}} |
|||
<syntaxhighlight lang="C#"> |
|||
using System; |
|||
using System.Numerics; |
|||
class CombinationsAndPermutations |
|||
{ |
|||
public static void Main(string[] args) |
|||
{ |
|||
Console.WriteLine(double.MaxValue); |
|||
Console.WriteLine("A sample of permutations from 1 to 12 with exact Integer arithmetic:"); |
|||
for (int n = 1; n <= 12; n++) |
|||
{ |
|||
int k = n / 2; |
|||
Console.WriteLine($"{n} P {k} = {Permutation(n, k)}"); |
|||
} |
|||
Console.WriteLine(); |
|||
Console.WriteLine("A sample of combinations from 10 to 60 with exact Integer arithmetic:"); |
|||
for (int n = 10; n <= 60; n += 5) |
|||
{ |
|||
int k = n / 2; |
|||
Console.WriteLine($"{n} C {k} = {Combination(n, k)}"); |
|||
} |
|||
Console.WriteLine(); |
|||
Console.WriteLine("A sample of permutations from 5 to 15000 displayed in floating point arithmetic:"); |
|||
Console.WriteLine($"{5} P {2} = {Display(Permutation(5, 2), 50)}"); |
|||
for (int n = 1000; n <= 15000; n += 1000) |
|||
{ |
|||
int k = n / 2; |
|||
Console.WriteLine($"{n} P {k} = {Display(Permutation(n, k), 50)}"); |
|||
} |
|||
Console.WriteLine(); |
|||
Console.WriteLine("A sample of combinations from 100 to 1000 displayed in floating point arithmetic:"); |
|||
for (int n = 100; n <= 1000; n += 100) |
|||
{ |
|||
int k = n / 2; |
|||
Console.WriteLine($"{n} C {k} = {Display(Combination(n, k), 50)}"); |
|||
} |
|||
} |
|||
private static string Display(BigInteger val, int precision) |
|||
{ |
|||
string s = val.ToString(); |
|||
// Ensure that we don't try to take a substring longer than what's available. |
|||
int actualPrecision = Math.Min(precision, s.Length - 1); // Adjusted to ensure it doesn't exceed string length |
|||
System.Text.StringBuilder sb = new System.Text.StringBuilder(); |
|||
if (s.Length > 1) // Check if the string has more than one character |
|||
{ |
|||
sb.Append(s.Substring(0, 1)); |
|||
sb.Append("."); |
|||
sb.Append(s.Substring(1, actualPrecision-1)); |
|||
} |
|||
else |
|||
{ |
|||
// If the string is only one digit, no need to insert a decimal point. |
|||
sb.Append(s); |
|||
} |
|||
sb.Append(" * 10^"); |
|||
sb.Append(s.Length - 1); |
|||
return sb.ToString(); |
|||
} |
|||
public static BigInteger Combination(int n, int k) |
|||
{ |
|||
// Select value with smallest intermediate results |
|||
// combination(n, k) = combination(n, n-k) |
|||
if (n - k < k) |
|||
{ |
|||
k = n - k; |
|||
} |
|||
BigInteger result = Permutation(n, k); |
|||
while (k > 0) |
|||
{ |
|||
result = result / k; |
|||
k--; |
|||
} |
|||
return result; |
|||
} |
|||
public static BigInteger Permutation(int n, int k) |
|||
{ |
|||
BigInteger result = BigInteger.One; |
|||
for (int i = n; i >= n - k + 1; i--) |
|||
{ |
|||
result = result * i; |
|||
} |
|||
return result; |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1.79769313486232E+308 |
|||
A sample of permutations from 1 to 12 with exact Integer arithmetic: |
|||
1 P 0 = 1 |
|||
2 P 1 = 2 |
|||
3 P 1 = 3 |
|||
4 P 2 = 12 |
|||
5 P 2 = 20 |
|||
6 P 3 = 120 |
|||
7 P 3 = 210 |
|||
8 P 4 = 1680 |
|||
9 P 4 = 3024 |
|||
10 P 5 = 30240 |
|||
11 P 5 = 55440 |
|||
12 P 6 = 665280 |
|||
A sample of combinations from 10 to 60 with exact Integer arithmetic: |
|||
10 C 5 = 252 |
|||
15 C 7 = 6435 |
|||
20 C 10 = 184756 |
|||
25 C 12 = 5200300 |
|||
30 C 15 = 155117520 |
|||
35 C 17 = 4537567650 |
|||
40 C 20 = 137846528820 |
|||
45 C 22 = 4116715363800 |
|||
50 C 25 = 126410606437752 |
|||
55 C 27 = 3824345300380220 |
|||
60 C 30 = 118264581564861424 |
|||
A sample of permutations from 5 to 15000 displayed in floating point arithmetic: |
|||
5 P 2 = 2. * 10^1 |
|||
1000 P 500 = 3.2978863640988537122024252070116261706996485697981 * 10^1433 |
|||
2000 P 1000 = 8.2415012140674255266380217928953202425839550211348 * 10^3167 |
|||
3000 P 1500 = 8.6229457673788561572282325050469704818001698192368 * 10^5015 |
|||
4000 P 2000 = 5.5146268042637929575202252487087217092097210095831 * 10^6937 |
|||
5000 P 2500 = 2.5959899179479570425022364594725223975158226787173 * 10^8914 |
|||
6000 P 3000 = 6.4684674799045492726351265543133876130483115297807 * 10^10934 |
|||
7000 P 3500 = 3.6978393541988590953223392044469547113117500019066 * 10^12991 |
|||
8000 P 4000 = 2.8347416494109128583587900207169062803923698647730 * 10^15079 |
|||
9000 P 4500 = 3.5613559022062915735922606191272180393638776777367 * 10^17194 |
|||
10000 P 5000 = 6.7310091721588924046678115055013992269082753633190 * 10^19333 |
|||
11000 P 5500 = 7.1714299723894354619599359891785521535675525394493 * 10^21494 |
|||
12000 P 6000 = 4.4778633072110971517945389774618813158941392935141 * 10^23675 |
|||
13000 P 6500 = 3.6571405647713639990172807053439865891697112165983 * 10^25874 |
|||
14000 P 7000 = 1.5680448683572888099973548116924953997328821172933 * 10^28090 |
|||
15000 P 7500 = 2.2454775022523692436484435950526532351441855443096 * 10^30321 |
|||
A sample of combinations from 100 to 1000 displayed in floating point arithmetic: |
|||
100 C 50 = 1.0089134454556419333481249725 * 10^29 |
|||
200 C 100 = 9.0548514656103281165404177077484163874504589675413 * 10^58 |
|||
300 C 150 = 9.3759702772827452793193754439064084879232655700081 * 10^88 |
|||
400 C 200 = 1.0295250013541443297297588032040198675721092538107 * 10^119 |
|||
500 C 250 = 1.1674431578827768292093473476217661965923008118031 * 10^149 |
|||
600 C 300 = 1.3510794199619426851447487797850453039723394544919 * 10^179 |
|||
700 C 350 = 1.5857433585316795487607022764754299250587342835720 * 10^209 |
|||
800 C 400 = 1.8804244186835312700958607615195351332156581822914 * 10^239 |
|||
900 C 450 = 2.2474718820660159573188913903771345843514101350359 * 10^269 |
|||
1000 C 500 = 2.7028824094543656951561469362597527549615200844654 * 10^299 |
|||
</pre> |
|||
=={{header|C++}}== |
|||
{{libheader|Boost}} |
|||
Compiled with <code>g++-10 -Wall -std=c++03</code>, linked with <code>-lgmp</code> |
|||
<syntaxhighlight lang="cpp">#include <boost/multiprecision/gmp.hpp> |
|||
#include <iostream> |
|||
using namespace boost::multiprecision; |
|||
mpz_int p(uint n, uint p) { |
|||
mpz_int r = 1; |
|||
mpz_int k = n - p; |
|||
while (n > k) |
|||
r *= n--; |
|||
return r; |
|||
} |
|||
mpz_int c(uint n, uint k) { |
|||
mpz_int r = p(n, k); |
|||
while (k) |
|||
r /= k--; |
|||
return r; |
|||
} |
|||
int main() { |
|||
for (uint i = 1u; i < 12u; i++) |
|||
std::cout << "P(12," << i << ") = " << p(12u, i) << std::endl; |
|||
for (uint i = 10u; i < 60u; i += 10u) |
|||
std::cout << "C(60," << i << ") = " << c(60u, i) << std::endl; |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>P(12,1) = 12 |
|||
P(12,2) = 132 |
|||
P(12,3) = 1320 |
|||
P(12,4) = 11880 |
|||
P(12,5) = 95040 |
|||
P(12,6) = 665280 |
|||
P(12,7) = 3991680 |
|||
P(12,8) = 19958400 |
|||
P(12,9) = 79833600 |
|||
P(12,10) = 239500800 |
|||
P(12,11) = 479001600 |
|||
C(60,10) = 75394027566 |
|||
C(60,20) = 4191844505805495 |
|||
C(60,30) = 118264581564861424 |
|||
C(60,40) = 4191844505805495 |
|||
C(60,50) = 75394027566</pre> |
|||
=={{header|Common Lisp}}== |
|||
<syntaxhighlight lang="lisp">(defun combinations (n k) |
|||
(cond ((or (< n k) (< k 0) (< n 0)) 0) |
|||
((= k 0) 1) |
|||
(t (do* ((i 1 (1+ i)) |
|||
(m n (1- m)) |
|||
(a m (* a m)) |
|||
(b i (* b i))) |
|||
((= i k) (/ a b)))))) |
|||
(defun permutations (n k) |
|||
(cond ((or (< n k) (< k 0) (< n 0)) 0) |
|||
((= k 0) 1) |
|||
(t (do* ((i 1 (1+ i)) |
|||
(m n (1- m)) |
|||
(a m (* a m))) |
|||
((= i k) a))))) |
|||
</syntaxhighlight> |
|||
=={{header|Crystal}}== |
|||
{{trans|Ruby}} |
|||
<syntaxhighlight lang="ruby">require "big" |
|||
include Math |
|||
struct Int |
|||
def permutation(k) |
|||
(self-k+1..self).product(1.to_big_i) |
|||
end |
|||
def combination(k) |
|||
self.permutation(k) // (1..k).product(1.to_big_i) |
|||
end |
|||
def big_permutation(k) |
|||
exp(lgamma_plus(self) - lgamma_plus(self-k)) |
|||
end |
|||
def big_combination(k) |
|||
exp( lgamma_plus(self) - lgamma_plus(self - k) - lgamma_plus(k)) |
|||
end |
|||
private def lgamma_plus(n) |
|||
lgamma(n+1) #lgamma is the natural log of gamma |
|||
end |
|||
end |
|||
p 12.permutation(9) #=> 79833600 |
|||
p 12.big_permutation(9) #=> 79833600.00000021 |
|||
p 60.combination(53) #=> 386206920 |
|||
p 145.big_permutation(133) #=> 1.6801459655817956e+243 |
|||
p 900.big_combination(450) #=> 2.247471882064647e+269 |
|||
p 1000.big_combination(969) #=> 7.602322407770517e+58 |
|||
p 15000.big_permutation(73) #=> 6.004137561717704e+304 |
|||
#That's about the maximum of Float: |
|||
p 15000.big_permutation(74) #=> Infinity |
|||
#Fixnum has no maximum: |
|||
p 15000.permutation(74) #=> 896237613852967826239917238565433149353074416025197784301593335243699358040738127950872384197159884905490054194835376498534786047382445592358843238688903318467070575184552953997615178973027752714539513893159815472948987921587671399790410958903188816684444202526779550201576117111844818124800000000000000000000 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
79833600 |
|||
79833600.00000021 |
|||
386206920 |
|||
1.6801459655817956e+243 |
|||
2.247471882064647e+269 |
|||
7.602322407770517e+58 |
|||
6.004137561717704e+304 |
|||
Infinity |
|||
896237613852967826239917238565433149353074416025197784301593335243699358040738127950872384197159884905490054194835376498534786047382445592358843238688903318467070575184552953997615178973027752714539513893159815472948987921587671399790410958903188816684444202526779550201576117111844818124800000000000000000000 |
|||
</pre> |
|||
=={{header|D}}== |
|||
{{trans|Ruby}} |
|||
<syntaxhighlight lang="d">import std.stdio, std.mathspecial, std.range, std.algorithm, |
|||
std.bigint, std.conv; |
|||
enum permutation = (in uint n, in uint k) pure => |
|||
reduce!q{a * b}(1.BigInt, iota(n - k + 1, n + 1)); |
|||
enum combination = (in uint n, in uint k) pure => |
|||
n.permutation(k) / reduce!q{a * b}(1.BigInt, iota(1, k + 1)); |
|||
enum bigPermutation = (in uint n, in uint k) => |
|||
exp(logGamma(n + 1) - logGamma(n - k + 1)); |
|||
enum bigCombination = (in uint n, in uint k) => |
|||
exp(logGamma(n + 1) - logGamma(n - k + 1) - logGamma(k + 1)); |
|||
void main() { |
|||
12.permutation(9).writeln; |
|||
12.bigPermutation(9).writeln; |
|||
60.combination(53).writeln; |
|||
145.bigPermutation(133).writeln; |
|||
900.bigCombination(450).writeln; |
|||
1_000.bigCombination(969).writeln; |
|||
15_000.bigPermutation(73).writeln; |
|||
15_000.bigPermutation(1185).writeln; |
|||
writefln("%(%s\\\n%)", 15_000.permutation(74).text.chunks(50)); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>79833600 |
|||
7.98336e+07 |
|||
386206920 |
|||
1.68015e+243 |
|||
2.24747e+269 |
|||
7.60232e+58 |
|||
6.00414e+304 |
|||
6.31335e+4927 |
|||
89623761385296782623991723856543314935307441602519\ |
|||
77843015933352436993580407381279508723841971598849\ |
|||
05490054194835376498534786047382445592358843238688\ |
|||
90331846707057518455295399761517897302775271453951\ |
|||
38931598154729489879215876713997904109589031888166\ |
|||
84444202526779550201576117111844818124800000000000\ |
|||
000000000</pre> |
|||
=={{header|EasyLang}}== |
|||
{{trans|Phix}} |
|||
<syntaxhighlight> |
|||
func perm x y . |
|||
z = 1 |
|||
for i = x - y + 1 to x |
|||
z *= i |
|||
. |
|||
return z |
|||
. |
|||
func fact x . |
|||
z = 1 |
|||
for i = 2 to x |
|||
z *= i |
|||
. |
|||
return z |
|||
. |
|||
func comb x y . |
|||
if x - y < y |
|||
y = x - y |
|||
. |
|||
return perm x y / fact y |
|||
. |
|||
# |
|||
e = 2.7182818284590452354 |
|||
func log n . |
|||
return log10 n / log10 e |
|||
. |
|||
func lstirling n . |
|||
if n < 10 |
|||
return lstirling (n + 1) - log (n + 1) |
|||
. |
|||
return 0.5 * log (2 * pi * n) + n * log (n / e + 1 / (12 * e * n)) |
|||
. |
|||
func$ tolog v . |
|||
h = v div log 10 |
|||
return pow e (v - h * log 10) & "e" & h |
|||
. |
|||
func$ permf n k . |
|||
return tolog (lstirling n - lstirling (n - k)) |
|||
. |
|||
func$ combf n k . |
|||
return tolog (lstirling n - lstirling (n - k) - lstirling k) |
|||
. |
|||
print "=> Exact results:" |
|||
for n = 1 to 12 |
|||
p = n div 3 |
|||
print "P(" & n & "," & p & ")=" & perm n p |
|||
. |
|||
# |
|||
# double has 53 bits for integer |
|||
# |
|||
for n = 10 step 10 to 50 |
|||
p = n div 3 |
|||
print "C(" & n & "," & p & ")=" & comb n p |
|||
. |
|||
# |
|||
print "" |
|||
print "=> Floating point approximations:" |
|||
for n in [ 5 50 500 1000 5000 15000 ] |
|||
p = n div 3 |
|||
print "P(" & n & "," & p & ")=" & permf n p |
|||
. |
|||
for n = 100 step 100 to 1000 |
|||
p = n div 3 |
|||
print "C(" & n & "," & p & ")=" & combf n p |
|||
. |
|||
</syntaxhighlight> |
|||
=={{header|EchoLisp}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
;; rename native functions according to task |
|||
(define-syntax-rule (Cnk n k) (Cnp n k)) |
|||
(define-syntax-rule (Ank n k) (Anp n k)) |
|||
(Cnk 10 1) |
|||
→ 10 |
|||
(lib 'bigint) ;; no floating point needed : use large integers |
|||
(Cnk 100 10) |
|||
→ 17310309456440 |
|||
(Cnk 1000 42) |
|||
→ 297242911333923795640059429176065863139989673213703918037987737481286092000 |
|||
(Ank 10 10) |
|||
→ 3628800 |
|||
(factorial 10) |
|||
→ 3628800 |
|||
(Ank 666 42) |
|||
→ 1029024198692120734765388598788124551227594950478035495578451793852872815678512303375588360 |
|||
1398831219998720000000000000 |
|||
</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
{{trans|Erlang}} |
|||
<syntaxhighlight lang="elixir">defmodule Combinations_permutations do |
|||
def perm(n, k), do: product(n - k + 1 .. n) |
|||
def comb(n, k), do: div( perm(n, k), product(1 .. k) ) |
|||
defp product(a..b) when a>b, do: 1 |
|||
defp product(list), do: Enum.reduce(list, 1, fn n, acc -> n * acc end) |
|||
def test do |
|||
IO.puts "\nA sample of permutations from 1 to 12:" |
|||
Enum.each(1..12, &show_perm(&1, div(&1, 3))) |
|||
IO.puts "\nA sample of combinations from 10 to 60:" |
|||
Enum.take_every(10..60, 10) |> Enum.each(&show_comb(&1, div(&1, 3))) |
|||
IO.puts "\nA sample of permutations from 5 to 15000:" |
|||
Enum.each([5,50,500,1000,5000,15000], &show_perm(&1, div(&1, 3))) |
|||
IO.puts "\nA sample of combinations from 100 to 1000:" |
|||
Enum.take_every(100..1000, 100) |> Enum.each(&show_comb(&1, div(&1, 3))) |
|||
end |
|||
defp show_perm(n, k), do: show_gen(n, k, "perm", &perm/2) |
|||
defp show_comb(n, k), do: show_gen(n, k, "comb", &comb/2) |
|||
defp show_gen(n, k, strfun, fun), do: |
|||
IO.puts "#{strfun}(#{n}, #{k}) = #{show_big(fun.(n, k), 40)}" |
|||
defp show_big(n, limit) do |
|||
strn = to_string(n) |
|||
if String.length(strn) < limit do |
|||
strn |
|||
else |
|||
{shown, hidden} = String.split_at(strn, limit) |
|||
"#{shown}... (#{String.length(hidden)} more digits)" |
|||
end |
|||
end |
|||
end |
|||
Combinations_permutations.test</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A sample of permutations from 1 to 12: |
|||
perm(1, 0) = 1 |
|||
perm(2, 0) = 1 |
|||
perm(3, 1) = 3 |
|||
perm(4, 1) = 4 |
|||
perm(5, 1) = 5 |
|||
perm(6, 2) = 30 |
|||
perm(7, 2) = 42 |
|||
perm(8, 2) = 56 |
|||
perm(9, 3) = 504 |
|||
perm(10, 3) = 720 |
|||
perm(11, 3) = 990 |
|||
perm(12, 4) = 11880 |
|||
A sample of combinations from 10 to 60: |
|||
comb(10, 3) = 120 |
|||
comb(20, 6) = 38760 |
|||
comb(30, 10) = 30045015 |
|||
comb(40, 13) = 12033222880 |
|||
comb(50, 16) = 4923689695575 |
|||
comb(60, 20) = 4191844505805495 |
|||
A sample of permutations from 5 to 15000: |
|||
perm(5, 1) = 5 |
|||
perm(50, 16) = 103017324974226408345600000 |
|||
perm(500, 166) = 3534874921742942787609361826601762306844... (395 more digits) |
|||
perm(1000, 333) = 5969326288503415089039701765900784280998... (932 more digits) |
|||
perm(5000, 1666) = 6856745757255674275484536940248896062234... (5986 more digits) |
|||
perm(15000, 5000) = 9649853988727493922014858805931295980792... (20430 more digits) |
|||
A sample of combinations from 100 to 1000: |
|||
comb(100, 33) = 294692427022540894366527900 |
|||
comb(200, 66) = 7269752545169278341527066651192738976755... (14 more digits) |
|||
comb(300, 100) = 4158251463258564744783383526326405580280... (42 more digits) |
|||
comb(400, 133) = 1257948684182108702133348475651965004491... (70 more digits) |
|||
comb(500, 166) = 3926028386194422755220408345072331428197... (97 more digits) |
|||
comb(600, 200) = 2506017783221402805005616770513228835202... (125 more digits) |
|||
comb(700, 233) = 8103203563339599904740453644031138232944... (152 more digits) |
|||
comb(800, 266) = 2645623362683627034288829299556124255091... (180 more digits) |
|||
comb(900, 300) = 1743356373296446642960730765085718347630... (208 more digits) |
|||
comb(1000, 333) = 5776134553147651669777486323549601722339... (235 more digits) |
|||
</pre> |
|||
=={{header|Erlang}}== |
|||
{{trans|Haskell}} |
|||
<syntaxhighlight lang="erlang"> |
|||
-module(combinations_permutations). |
|||
-export([test/0]). |
|||
perm(N, K) -> |
|||
product(lists:seq(N - K + 1, N)). |
|||
comb(N, K) -> |
|||
perm(N, K) div product(lists:seq(1, K)). |
|||
product(List) -> |
|||
lists:foldl(fun(N, Acc) -> N * Acc end, 1, List). |
|||
test() -> |
|||
io:format("\nA sample of permutations from 1 to 12:\n"), |
|||
[show_perm({N, N div 3}) || N <- lists:seq(1, 12)], |
|||
io:format("\nA sample of combinations from 10 to 60:\n"), |
|||
[show_comb({N, N div 3}) || N <- lists:seq(10, 60, 10)], |
|||
io:format("\nA sample of permutations from 5 to 15000:\n"), |
|||
[show_perm({N, N div 3}) || N <- [5,50,500,1000,5000,15000]], |
|||
io:format("\nA sample of combinations from 100 to 1000:\n"), |
|||
[show_comb({N, N div 3}) || N <- lists:seq(100, 1000, 100)], |
|||
ok. |
|||
show_perm({N, K}) -> |
|||
show_gen(N, K, "perm", fun perm/2). |
|||
show_comb({N, K}) -> |
|||
show_gen(N, K, "comb", fun comb/2). |
|||
show_gen(N, K, StrFun, Fun) -> |
|||
io:format("~s(~p, ~p) = ~s\n",[StrFun, N, K, show_big(Fun(N, K), 40)]). |
|||
show_big(N, Limit) -> |
|||
StrN = integer_to_list(N), |
|||
case length(StrN) < Limit of |
|||
true -> |
|||
StrN; |
|||
false -> |
|||
{Shown, Hidden} = lists:split(Limit, StrN), |
|||
io_lib:format("~s... (~p more digits)", [Shown, length(Hidden)]) |
|||
end. |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre style="font-size:80%"> |
|||
A sample of permutations from 1 to 12: |
|||
perm(1, 0) = 1 |
|||
perm(2, 0) = 1 |
|||
perm(3, 1) = 3 |
|||
perm(4, 1) = 4 |
|||
perm(5, 1) = 5 |
|||
perm(6, 2) = 30 |
|||
perm(7, 2) = 42 |
|||
perm(8, 2) = 56 |
|||
perm(9, 3) = 504 |
|||
perm(10, 3) = 720 |
|||
perm(11, 3) = 990 |
|||
perm(12, 4) = 11880 |
|||
A sample of combinations from 10 to 60: |
|||
comb(10, 3) = 120 |
|||
comb(20, 6) = 38760 |
|||
comb(30, 10) = 30045015 |
|||
comb(40, 13) = 12033222880 |
|||
comb(50, 16) = 4923689695575 |
|||
comb(60, 20) = 4191844505805495 |
|||
A sample of permutations from 5 to 15000: |
|||
perm(5, 1) = 5 |
|||
perm(50, 16) = 103017324974226408345600000 |
|||
perm(500, 166) = 3534874921742942787609361826601762306844... (395 more digits) |
|||
perm(1000, 333) = 5969326288503415089039701765900784280998... (932 more digits) |
|||
perm(5000, 1666) = 6856745757255674275484536940248896062234... (5986 more digits) |
|||
perm(15000, 5000) = 9649853988727493922014858805931295980792... (20430 more digits) |
|||
A sample of combinations from 100 to 1000: |
|||
comb(100, 33) = 294692427022540894366527900 |
|||
comb(200, 66) = 7269752545169278341527066651192738976755... (14 more digits) |
|||
comb(300, 100) = 4158251463258564744783383526326405580280... (42 more digits) |
|||
comb(400, 133) = 1257948684182108702133348475651965004491... (70 more digits) |
|||
comb(500, 166) = 3926028386194422755220408345072331428197... (97 more digits) |
|||
comb(600, 200) = 2506017783221402805005616770513228835202... (125 more digits) |
|||
comb(700, 233) = 8103203563339599904740453644031138232944... (152 more digits) |
|||
comb(800, 266) = 2645623362683627034288829299556124255091... (180 more digits) |
|||
comb(900, 300) = 1743356373296446642960730765085718347630... (208 more digits) |
|||
comb(1000, 333) = 5776134553147651669777486323549601722339... (235 more digits) |
|||
</pre> |
|||
=={{header|Factor}}== |
|||
As with Racket, these operations are built in and Factor has unlimited integers. |
|||
<syntaxhighlight lang="factor">USING: math.combinatorics prettyprint ; |
|||
1000 10 nCk . ! 263409560461970212832400 |
|||
1000 10 nPk . ! 955860613004397508326213120000</syntaxhighlight> |
|||
=={{header|FreeBASIC}}== |
|||
{{trans|Visual Basic .NET}} |
|||
<syntaxhighlight lang="freebasic">Function PermBig(x As Long, y As Long) As ULongint |
|||
Dim As Long i |
|||
Dim As Longint z = 1 |
|||
For i = x - y + 1 To x |
|||
z = z * i |
|||
Next i |
|||
Return (z) |
|||
End Function |
|||
Function FactBig(x As Long) As ULongint |
|||
Dim As Long i |
|||
Dim As Longint z = 1 |
|||
For i = 2 To x |
|||
z = z * i |
|||
Next i |
|||
Return (z) |
|||
End Function |
|||
Function CombBig(Byval x As Long, Byval y As Long) As Double |
|||
If y > x Then |
|||
Return (0) |
|||
Elseif x = y Then |
|||
Return (1) |
|||
Else |
|||
If x - y < y Then y = x - y |
|||
Return (PermBig(x, y) / FactBig(y)) |
|||
End If |
|||
End Function |
|||
Dim As Long i, j |
|||
Print "-- Long Integer - Permutations - from 1 to 12" |
|||
For i = 1 To 12 |
|||
For j = 1 To i |
|||
Print "P(" & i & "," & j & ")=" & Str(PermBig(i, j)) & " "; |
|||
Next j |
|||
Print "" |
|||
Next i |
|||
Print Chr(10) & "-- Float integer - Combinations from 10 to 60" |
|||
For i = 10 To 60 Step 10 |
|||
For j = 1 To i Step i \ 5 |
|||
Print "C(" & i & "," & j & ")=" & Str(CombBig(i, j)) & " "; |
|||
Next j |
|||
Print "" |
|||
Next i |
|||
Print Chr(10) & "-- Float integer - Permutations from 5000 to 15000" |
|||
For i = 5000 To 15000 Step 5000 |
|||
For j = 10 To 50 Step 20 |
|||
Print "P(" & i & "," & j & ")=" & Str(PermBig(i, j)) & " "; |
|||
Next j |
|||
Print "" |
|||
Next i |
|||
Print Chr(10) & "-- Float integer - Combinations from 200 to 1000" |
|||
For i = 200 To 1000 Step 200 |
|||
For j = 20 To 100 Step 20 |
|||
Print "C(" & i & "," & j & ")=" & Str(CombBig(i, j)) & " "; |
|||
Next j |
|||
Print "" |
|||
Next i |
|||
Sleep</syntaxhighlight> |
|||
=={{header|Go}}== |
|||
Go has arbitrary-length maths in the standard math/big library; no need for floating-point approximations at this level. |
|||
<syntaxhighlight lang="go"> |
|||
package main |
|||
import ( |
|||
"fmt" |
|||
"math/big" |
|||
) |
|||
func main() { |
|||
var n, p int64 |
|||
fmt.Printf("A sample of permutations from 1 to 12:\n") |
|||
for n = 1; n < 13; n++ { |
|||
p = n / 3 |
|||
fmt.Printf("P(%d,%d) = %d\n", n, p, perm(big.NewInt(n), big.NewInt(p))) |
|||
} |
|||
fmt.Printf("\nA sample of combinations from 10 to 60:\n") |
|||
for n = 10; n < 61; n += 10 { |
|||
p = n / 3 |
|||
fmt.Printf("C(%d,%d) = %d\n", n, p, comb(big.NewInt(n), big.NewInt(p))) |
|||
} |
|||
fmt.Printf("\nA sample of permutations from 5 to 15000:\n") |
|||
nArr := [...]int64{5, 50, 500, 1000, 5000, 15000} |
|||
for _, n = range nArr { |
|||
p = n / 3 |
|||
fmt.Printf("P(%d,%d) = %d\n", n, p, perm(big.NewInt(n), big.NewInt(p))) |
|||
} |
|||
fmt.Printf("\nA sample of combinations from 100 to 1000:\n") |
|||
for n = 100; n < 1001; n += 100 { |
|||
p = n / 3 |
|||
fmt.Printf("C(%d,%d) = %d\n", n, p, comb(big.NewInt(n), big.NewInt(p))) |
|||
} |
|||
} |
|||
func fact(n *big.Int) *big.Int { |
|||
if n.Sign() < 1 { |
|||
return big.NewInt(0) |
|||
} |
|||
r := big.NewInt(1) |
|||
i := big.NewInt(2) |
|||
for i.Cmp(n) < 1 { |
|||
r.Mul(r, i) |
|||
i.Add(i, big.NewInt(1)) |
|||
} |
|||
return r |
|||
} |
|||
func perm(n, k *big.Int) *big.Int { |
|||
r := fact(n) |
|||
r.Div(r, fact(n.Sub(n, k))) |
|||
return r |
|||
} |
|||
func comb(n, r *big.Int) *big.Int { |
|||
if r.Cmp(n) == 1 { |
|||
return big.NewInt(0) |
|||
} |
|||
if r.Cmp(n) == 0 { |
|||
return big.NewInt(1) |
|||
} |
|||
c := fact(n) |
|||
den := fact(n.Sub(n, r)) |
|||
den.Mul(den, fact(r)) |
|||
c.Div(c, den) |
|||
return c |
|||
} |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre>A sample of permutations from 1 to 12: |
|||
P(1,0) = 1 |
|||
P(2,0) = 1 |
|||
P(3,1) = 3 |
|||
P(4,1) = 4 |
|||
P(5,1) = 5 |
|||
P(6,2) = 30 |
|||
P(7,2) = 42 |
|||
P(8,2) = 56 |
|||
P(9,3) = 504 |
|||
P(10,3) = 720 |
|||
P(11,3) = 990 |
|||
P(12,4) = 11880 |
|||
A sample of combinations from 10 to 60: |
|||
C(10,3) = 120 |
|||
C(20,6) = 38760 |
|||
C(30,10) = 30045015 |
|||
C(40,13) = 12033222880 |
|||
C(50,16) = 4923689695575 |
|||
C(60,20) = 4191844505805495 |
|||
A sample of permutations from 5 to 15000: |
|||
P(5,1) = 5 |
|||
P(50,16) = 103017324974226408345600000 |
|||
P(500,166) = 353487492174294278760936182660176230684400287910609032932176169251145051223056590013516735448538086130105926216996155913554025250125337170813019594283712354977999534430770809915541863294344717641926832713607917635838943102385935821177067602075180371673503765613359169210620516084434587852075431010684540863423686685437846488590916158047347611875355166780660833377163468853354607169353747005440000000000000000000000000000000000000000000 |
|||
P(1000,333) = 596932628850341508903970176590078428099818947656708993181003187015748137551596090897395098770177006143741943000028735297176540996715216223470117008188290845824893667956971794591724165149886070514986743432208287422668258597883938335639789463537748828480742878588232053442156529356123644254034620250998013239063050800571901268462622323786888857845397534124006543754044331948142416200311556601875197681493636464229808874876131434533721937546154413110195799580966669097512255452752067457629468146295647406985227990184437533735467426422585063839734564755495294687791091277426861971582062496498138090957027659529000216472781766770467939751274131497380920782541878343751496719223481266229644276166815775979972070711062842180838624567600323874889368489920534418201154996144776696986749038638993937273035934558675329887334851616951614782042039326589303359315137179445599073086196250614391361241088000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
|||
P(5000,1666) = 685674575725567427548453694024889606223415671024481949274389525763165050940278456955930987049278913288741555958551429473866794447094151777406284837935079289013939976368320856320075398810321021264609367677596630017492662476653457696667818345302032079158497998678962485919859205035598026552321633034034950067207086196635562039504231368320682342175536748176816241129369211418155064764285518551122913802314264757797230065345837585112169021234001053819461909997341171332285483908469793127022101882927191957584158820572953454348525922376264896938701700503579[cut for brevity] |
|||
P(15000,5000) = 964985398872749392201485880593129598079228168868086089709069882934904327326041434448685068557423519588782990996839148935743422697293448340149394869739166392123184483900811562453898657822593544251663672426442538772790754374376708208571908721887559582227891355612508675254239851818491849618848602192999811776790423150460291684931309968390568370095954400889615967984376006072547506893620140168365357740946620575769516153753735678390720704316317251046076250691800213698137901479234159657387339301806781869228964210268691780310799227446113809960921205463002689680686581917548426454723087176124161728203856922785131850458595700123281745279678944233081992533251647291980003523846698046974475328766195265764029672828687155439288711515137638802309221117722696141292043413736618293499869841412502567093112620576877254953509763190120514494690844850900732795773648193199871673637389424514221019995024902360799221264651063770768194819355718580618775786102220736660007307021195929713637615667876228769039112504881578385857681786265840651390718446642041061982261630233585694136722143048873223923363402206453540375800805584706454386378553117095912890292078608807203370350094921116703330118357576158786202069866488676813049328910886961677198798213135372964228023956951408480830806905842004749290253667472325116488994202675719755525469268037451046892994419861436389890344224919839492952550142350743[cut for brevity] |
|||
A sample of combinations from 100 to 1000: |
|||
C(100,33) = 294692427022540894366527900 |
|||
C(200,66) = 726975254516927834152706665119273897675502691419359300 |
|||
C(300,100) = 4158251463258564744783383526326405580280466005743648708663033657304756328324008620 |
|||
C(400,133) = 12579486841821087021333484756519650044917494358375678689903944407062661887691782714561293494166382210572895600 |
|||
C(500,166) = 39260283861944227552204083450723314281973490135301528555644859907093815055309467400410307687655531369748267877388321068535356654999949000 |
|||
C(600,200) = 250601778322140280500561677051322883520255102508793389473094343332441398315528846878026090182866148274621477126087990864486283260622128340138769443055475567389095596 |
|||
C(700,233) = 810320356333959990474045364403113823294492031194214481466666874664632951279413378341573227990559808332117096088495529108312831240206642074673862825014526456696556162909686658807978793453220000 |
|||
C(800,266) = 2645623362683627034288829299556124255091524045015061559880110850588357798837813526621954238671844949835878984342140544523564918954064307529607727040078866833961879433579846596361407958192581870170248962672479120257018000 |
|||
C(900,300) = 17433563732964466429607307650857183476303419689548896834573896609295907147982188408607179689430757813632301567003238290404591375673438892792913992016448098783043956457942357838233534288303678577768883350818012950587783262800434058273110416350965200 |
|||
C(1000,333) = 57761345531476516697774863235496017223394580195002114171799054793660405129610824218694609475292335509897216233568933163108481350037180876217607177657236327948642711456536116349650593787069554795812874358426845137087373717847050642650744775784499136594696491030795647099932000 |
|||
</pre> |
|||
=={{header|Haskell}}== |
|||
The Haskell Integer type supports arbitrary precision so floating point approximation is not needed. |
|||
<syntaxhighlight lang="haskell">perm :: Integer -> Integer -> Integer |
|||
perm n k = product [n-k+1..n] |
|||
comb :: Integer -> Integer -> Integer |
|||
comb n k = perm n k `div` product [1..k] |
|||
main :: IO () |
|||
main = do |
|||
let showBig maxlen b = |
|||
let st = show b |
|||
stlen = length st |
|||
in if stlen < maxlen then st else take maxlen st ++ "... (" ++ show (stlen-maxlen) ++ " more digits)" |
|||
let showPerm pr = |
|||
putStrLn $ "perm(" ++ show n ++ "," ++ show k ++ ") = " ++ showBig 40 (perm n k) |
|||
where n = fst pr |
|||
k = snd pr |
|||
let showComb pr = |
|||
putStrLn $ "comb(" ++ show n ++ "," ++ show k ++ ") = " ++ showBig 40 (comb n k) |
|||
where n = fst pr |
|||
k = snd pr |
|||
putStrLn "A sample of permutations from 1 to 12:" |
|||
mapM_ showPerm [(n, n `div` 3) | n <- [1..12] ] |
|||
putStrLn "" |
|||
putStrLn "A sample of combinations from 10 to 60:" |
|||
mapM_ showComb [(n, n `div` 3) | n <- [10,20..60] ] |
|||
putStrLn "" |
|||
putStrLn "A sample of permutations from 5 to 15000:" |
|||
mapM_ showPerm [(n, n `div` 3) | n <- [5,50,500,1000,5000,15000] ] |
|||
putStrLn "" |
|||
putStrLn "A sample of combinations from 100 to 1000:" |
|||
mapM_ showComb [(n, n `div` 3) | n <- [100,200..1000] ] |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="font-size:80%">A sample of permutations from 1 to 12: |
|||
perm(1,0) = 1 |
|||
perm(2,0) = 1 |
|||
perm(3,1) = 3 |
|||
perm(4,1) = 4 |
|||
perm(5,1) = 5 |
|||
perm(6,2) = 30 |
|||
perm(7,2) = 42 |
|||
perm(8,2) = 56 |
|||
perm(9,3) = 504 |
|||
perm(10,3) = 720 |
|||
perm(11,3) = 990 |
|||
perm(12,4) = 11880 |
|||
A sample of combinations from 10 to 60: |
|||
comb(10,3) = 120 |
|||
comb(20,6) = 38760 |
|||
comb(30,10) = 30045015 |
|||
comb(40,13) = 12033222880 |
|||
comb(50,16) = 4923689695575 |
|||
comb(60,20) = 4191844505805495 |
|||
A sample of permutations from 5 to 15000: |
|||
perm(5,1) = 5 |
|||
perm(50,16) = 103017324974226408345600000 |
|||
perm(500,166) = 3534874921742942787609361826601762306844... (395 more digits) |
|||
perm(1000,333) = 5969326288503415089039701765900784280998... (932 more digits) |
|||
perm(5000,1666) = 6856745757255674275484536940248896062234... (5986 more digits) |
|||
perm(15000,5000) = 9649853988727493922014858805931295980792... (20430 more digits) |
|||
A sample of combinations from 100 to 1000: |
|||
comb(100,33) = 294692427022540894366527900 |
|||
comb(200,66) = 7269752545169278341527066651192738976755... (14 more digits) |
|||
comb(300,100) = 4158251463258564744783383526326405580280... (42 more digits) |
|||
comb(400,133) = 1257948684182108702133348475651965004491... (70 more digits) |
|||
comb(500,166) = 3926028386194422755220408345072331428197... (97 more digits) |
|||
comb(600,200) = 2506017783221402805005616770513228835202... (125 more digits) |
|||
comb(700,233) = 8103203563339599904740453644031138232944... (152 more digits) |
|||
comb(800,266) = 2645623362683627034288829299556124255091... (180 more digits) |
|||
comb(900,300) = 1743356373296446642960730765085718347630... (208 more digits) |
|||
comb(1000,333) = 5776134553147651669777486323549601722339... (235 more digits) |
|||
</pre> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
|||
As with several other languages here, Icon and Unicon can handle unlimited integers so |
|||
floating point approximation isn't needed. |
|||
The sample here gives a few representative values to shorten the output. |
|||
<syntaxhighlight lang="unicon">procedure main() |
|||
write("P(4,2) = ",P(4,2)) |
|||
write("P(8,2) = ",P(8,2)) |
|||
write("P(10,8) = ",P(10,8)) |
|||
write("C(10,8) = ",C(10,8)) |
|||
write("C(20,8) = ",C(20,8)) |
|||
write("C(60,58) = ",C(60,58)) |
|||
write("P(1000,10) = ",P(1000,10)) |
|||
write("P(1000,20) = ",P(1000,20)) |
|||
write("P(15000,2) = ",P(15000,2)) |
|||
write("C(1000,10) = ",C(1000,10)) |
|||
write("C(1000,999) = ",C(1000,999)) |
|||
write("C(1000,1000) = ",C(1000,1000)) |
|||
write("C(15000,14998) = ",C(15000,14998)) |
|||
end |
|||
procedure C(n,k) |
|||
every (d:=1) *:= 2 to k |
|||
return P(n,k)/d |
|||
end |
|||
procedure P(n,k) |
|||
every (p:=1) *:= (n-k+1) to n |
|||
return p |
|||
end</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
->cap |
|||
P(4,2) = 12 |
|||
P(8,2) = 56 |
|||
P(10,8) = 1814400 |
|||
C(10,8) = 45 |
|||
C(20,8) = 125970 |
|||
C(60,58) = 1770 |
|||
P(1000,10) = 955860613004397508326213120000 |
|||
P(1000,20) = 825928413359200443640727373872992573951185652339949568000000 |
|||
P(15000,2) = 224985000 |
|||
C(1000,10) = 263409560461970212832400 |
|||
C(1000,999) = 1000 |
|||
C(1000,1000) = 1 |
|||
C(15000,14998) = 112492500 |
|||
-> |
|||
</pre> |
|||
=={{header|J}}== |
|||
It looks like this task wants a count of the available combinations or permutations (given a set of 3 things, there are three distinct combinations of 2 of them) rather than a representation of the available combinations or permutations (given a set of three things, the distinct combinations of 2 of them may be identified by <0,1>, <0,2> and <1,2>)). |
|||
Also, this task allows a language to show off its abilities to support floating point numbers outside the usual range of 64 bit IEEE floating point numbers. We'll neglect that part. |
|||
Implementation: |
|||
<syntaxhighlight lang="j">C=: ! |
|||
P=: (%&!&x:~ * <:)"0</syntaxhighlight> |
|||
! is a primitive, but we will give it a name (<code>C</code>) for this task. |
|||
Example use (P is permutations, C is combinations): |
|||
<syntaxhighlight lang="j"> P table 1+i.12 |
|||
┌──┬─────────────────────────────────────────────────────────────┐ |
|||
│P │1 2 3 4 5 6 7 8 9 10 11 12│ |
|||
├──┼─────────────────────────────────────────────────────────────┤ |
|||
│ 1│1 2 6 24 120 720 5040 40320 362880 3628800 39916800 479001600│ |
|||
│ 2│0 1 3 12 60 360 2520 20160 181440 1814400 19958400 239500800│ |
|||
│ 3│0 0 1 4 20 120 840 6720 60480 604800 6652800 79833600│ |
|||
│ 4│0 0 0 1 5 30 210 1680 15120 151200 1663200 19958400│ |
|||
│ 5│0 0 0 0 1 6 42 336 3024 30240 332640 3991680│ |
|||
│ 6│0 0 0 0 0 1 7 56 504 5040 55440 665280│ |
|||
│ 7│0 0 0 0 0 0 1 8 72 720 7920 95040│ |
|||
│ 8│0 0 0 0 0 0 0 1 9 90 990 11880│ |
|||
│ 9│0 0 0 0 0 0 0 0 1 10 110 1320│ |
|||
│10│0 0 0 0 0 0 0 0 0 1 11 132│ |
|||
│11│0 0 0 0 0 0 0 0 0 0 1 12│ |
|||
│12│0 0 0 0 0 0 0 0 0 0 0 1│ |
|||
└──┴─────────────────────────────────────────────────────────────┘ |
|||
C table 10+10*i.6x |
|||
┌──┬─────────────────────────────────────────────────────────────────┐ |
|||
│C │10 20 30 40 50 60│ |
|||
├──┼─────────────────────────────────────────────────────────────────┤ |
|||
│10│ 1 184756 30045015 847660528 10272278170 75394027566│ |
|||
│20│ 0 1 30045015 137846528820 47129212243960 4191844505805495│ |
|||
│30│ 0 0 1 847660528 47129212243960 118264581564861424│ |
|||
│40│ 0 0 0 1 10272278170 4191844505805495│ |
|||
│50│ 0 0 0 0 1 75394027566│ |
|||
│60│ 0 0 0 0 0 1│ |
|||
└──┴─────────────────────────────────────────────────────────────────┘ |
|||
5 P 100 |
|||
7.77718e155 |
|||
100 P 200 |
|||
8.45055e216 |
|||
300 P 400 |
|||
2.09224e254 |
|||
700 P 800 |
|||
3.18349e287 |
|||
5 C 100 |
|||
75287520 |
|||
100 C 200 |
|||
9.05485e58 |
|||
300 C 400 |
|||
2.24185e96 |
|||
700 C 800 |
|||
3.41114e129</syntaxhighlight> |
|||
=={{header|Java}}== |
|||
The second part of this task implies that the computations are performed in floating point arithmetic. However, the maximum value of a double in Java is 1.7976931348623157E308. Hence, larger computations would overflow. As a result, this task was interpreted so that “using” means “displayed”. |
|||
<syntaxhighlight lang="java"> |
|||
import java.math.BigInteger; |
|||
public class CombinationsAndPermutations { |
|||
public static void main(String[] args) { |
|||
System.out.println(Double.MAX_VALUE); |
|||
System.out.println("A sample of permutations from 1 to 12 with exact Integer arithmetic:"); |
|||
for ( int n = 1 ; n <= 12 ; n++ ) { |
|||
int k = n / 2; |
|||
System.out.printf("%d P %d = %s%n", n, k, permutation(n, k)); |
|||
} |
|||
System.out.println(); |
|||
System.out.println("A sample of combinations from 10 to 60 with exact Integer arithmetic:"); |
|||
for ( int n = 10 ; n <= 60 ; n += 5 ) { |
|||
int k = n / 2; |
|||
System.out.printf("%d C %d = %s%n", n, k, combination(n, k)); |
|||
} |
|||
System.out.println(); |
|||
System.out.println("A sample of permutations from 5 to 15000 displayed in floating point arithmetic:"); |
|||
System.out.printf("%d P %d = %s%n", 5, 2, display(permutation(5, 2), 50)); |
|||
for ( int n = 1000 ; n <= 15000 ; n += 1000 ) { |
|||
int k = n / 2; |
|||
System.out.printf("%d P %d = %s%n", n, k, display(permutation(n, k), 50)); |
|||
} |
|||
System.out.println(); |
|||
System.out.println("A sample of combinations from 100 to 1000 displayed in floating point arithmetic:"); |
|||
for ( int n = 100 ; n <= 1000 ; n += 100 ) { |
|||
int k = n / 2; |
|||
System.out.printf("%d C %d = %s%n", n, k, display(combination(n, k), 50)); |
|||
} |
|||
} |
|||
private static String display(BigInteger val, int precision) { |
|||
String s = val.toString(); |
|||
precision = Math.min(precision, s.length()); |
|||
StringBuilder sb = new StringBuilder(); |
|||
sb.append(s.substring(0, 1)); |
|||
sb.append("."); |
|||
sb.append(s.substring(1, precision)); |
|||
sb.append(" * 10^"); |
|||
sb.append(s.length()-1); |
|||
return sb.toString(); |
|||
} |
|||
public static BigInteger combination(int n, int k) { |
|||
// Select value with smallest intermediate results |
|||
// combination(n, k) = combination(n, n-k) |
|||
if ( n-k < k ) { |
|||
k = n-k; |
|||
} |
|||
BigInteger result = permutation(n, k); |
|||
while ( k > 0 ) { |
|||
result = result.divide(BigInteger.valueOf(k)); |
|||
k--; |
|||
} |
|||
return result; |
|||
} |
|||
public static BigInteger permutation(int n, int k) { |
|||
BigInteger result = BigInteger.ONE; |
|||
for ( int i = n ; i >= n-k+1 ; i-- ) { |
|||
result = result.multiply(BigInteger.valueOf(i)); |
|||
} |
|||
return result; |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1.7976931348623157E308 |
|||
A sample of permutations from 1 to 12 with exact Integer arithmetic: |
|||
1 P 0 = 1 |
|||
2 P 1 = 2 |
|||
3 P 1 = 3 |
|||
4 P 2 = 12 |
|||
5 P 2 = 20 |
|||
6 P 3 = 120 |
|||
7 P 3 = 210 |
|||
8 P 4 = 1680 |
|||
9 P 4 = 3024 |
|||
10 P 5 = 30240 |
|||
11 P 5 = 55440 |
|||
12 P 6 = 665280 |
|||
A sample of combinations from 10 to 60 with exact Integer arithmetic: |
|||
10 C 5 = 252 |
|||
15 C 7 = 6435 |
|||
20 C 10 = 184756 |
|||
25 C 12 = 5200300 |
|||
30 C 15 = 155117520 |
|||
35 C 17 = 4537567650 |
|||
40 C 20 = 137846528820 |
|||
45 C 22 = 4116715363800 |
|||
50 C 25 = 126410606437752 |
|||
55 C 27 = 3824345300380220 |
|||
60 C 30 = 118264581564861424 |
|||
A sample of permutations from 5 to 15000 displayed in floating point arithmetic: |
|||
5 P 2 = 2.0 * 10^1 |
|||
1000 P 500 = 3.2978863640988537122024252070116261706996485697981 * 10^1433 |
|||
2000 P 1000 = 8.2415012140674255266380217928953202425839550211348 * 10^3167 |
|||
3000 P 1500 = 8.6229457673788561572282325050469704818001698192368 * 10^5015 |
|||
4000 P 2000 = 5.5146268042637929575202252487087217092097210095831 * 10^6937 |
|||
5000 P 2500 = 2.5959899179479570425022364594725223975158226787173 * 10^8914 |
|||
6000 P 3000 = 6.4684674799045492726351265543133876130483115297807 * 10^10934 |
|||
7000 P 3500 = 3.6978393541988590953223392044469547113117500019066 * 10^12991 |
|||
8000 P 4000 = 2.8347416494109128583587900207169062803923698647730 * 10^15079 |
|||
9000 P 4500 = 3.5613559022062915735922606191272180393638776777367 * 10^17194 |
|||
10000 P 5000 = 6.7310091721588924046678115055013992269082753633190 * 10^19333 |
|||
11000 P 5500 = 7.1714299723894354619599359891785521535675525394493 * 10^21494 |
|||
12000 P 6000 = 4.4778633072110971517945389774618813158941392935141 * 10^23675 |
|||
13000 P 6500 = 3.6571405647713639990172807053439865891697112165983 * 10^25874 |
|||
14000 P 7000 = 1.5680448683572888099973548116924953997328821172933 * 10^28090 |
|||
15000 P 7500 = 2.2454775022523692436484435950526532351441855443096 * 10^30321 |
|||
A sample of combinations from 100 to 1000 displayed in floating point arithmetic: |
|||
100 C 50 = 1.00891344545564193334812497256 * 10^29 |
|||
200 C 100 = 9.0548514656103281165404177077484163874504589675413 * 10^58 |
|||
300 C 150 = 9.3759702772827452793193754439064084879232655700081 * 10^88 |
|||
400 C 200 = 1.0295250013541443297297588032040198675721092538107 * 10^119 |
|||
500 C 250 = 1.1674431578827768292093473476217661965923008118031 * 10^149 |
|||
600 C 300 = 1.3510794199619426851447487797850453039723394544919 * 10^179 |
|||
700 C 350 = 1.5857433585316795487607022764754299250587342835720 * 10^209 |
|||
800 C 400 = 1.8804244186835312700958607615195351332156581822914 * 10^239 |
|||
900 C 450 = 2.2474718820660159573188913903771345843514101350359 * 10^269 |
|||
1000 C 500 = 2.7028824094543656951561469362597527549615200844654 * 10^299 |
|||
</pre> |
|||
=={{header|jq}}== |
|||
The C implementation of jq approximates large integers by IEEE 754 64-bit floats, |
|||
and only supports tgamma (true gamma), and thus beyond about 1e308 all accuracy is lost. |
|||
On the other hand, gojq, the Go implementation, supports |
|||
unbounded-precision integer arithmetic, |
|||
and the `permutation` and `combination` functions below are |
|||
implemented so as to preserve precision. |
|||
<syntaxhighlight lang="jq"> |
|||
def permutation(k): . as $n |
|||
| reduce range($n-k+1; 1+$n) as $i (1; . * $i); |
|||
def combination(k): . as $n |
|||
| if k > ($n/2) then combination($n-k) |
|||
else reduce range(0; k) as $i (1; (. * ($n - $i)) / ($i + 1)) |
|||
end; |
|||
# natural log of n! |
|||
def log_factorial: (1+.) | tgamma | log; |
|||
def log_permutation(k): |
|||
(log_factorial - ((.-k) | log_factorial)); |
|||
def log_combination(k): |
|||
(log_factorial - ((. - k)|log_factorial) - (k|log_factorial)); |
|||
def big_permutation(k): log_permutation(k) | exp; |
|||
def big_combination(k): log_combination(k) | exp; |
|||
</syntaxhighlight> |
|||
'''Examples using the C implementation''': |
|||
<pre> |
|||
12 | permutation(9) #=> 79833600 |
|||
12 | big_permutation(9) #=> 79833599.99999964 |
|||
60 | combination(53) #=> 386206920 |
|||
60 | big_combination(53) #=> 386206920.0000046 |
|||
145 | big_permutation(133) #=> 1.6801459655817956e+243 |
|||
170 | big_permutation(133) #=> 5.272846415658284e+263 |
|||
</pre> |
|||
'''Examples using gojq, the Go implementation''' |
|||
<pre> |
|||
60 | combinations(30) #=> 118264581564861424 |
|||
1000 | combination(333) | tostring | "\(.[:40]) ... (\(length) digits in all)" |
|||
#=> 5776134553147651669777486323549601722339 ... (275 digits in all) |
|||
</pre> |
|||
=={{header|Julia}}== |
|||
Infix operators are interpreted by Julia's parser, and (to my knowledge) it isn't possible to define arbitrary characters as such operators. However one can define Unicode "Symbol, Math" characters as infix operators. This solution uses ⊞ for combinations and ⊠ for permutations. An alternative to using the <tt>FloatingPoint</tt> versions of these operators for large numbers would be to use arbitrary precision integers, <tt>BigInt</tt>. |
|||
'''Functions''' |
|||
<syntaxhighlight lang="julia"> |
|||
function Base.binomial{T<:FloatingPoint}(n::T, k::T) |
|||
exp(lfact(n) - lfact(n - k) - lfact(k)) |
|||
end |
|||
function Base.factorial{T<:FloatingPoint}(n::T, k::T) |
|||
exp(lfact(n) - lfact(k)) |
|||
end |
|||
⊞{T<:Real}(n::T, k::T) = binomial(n, k) |
|||
⊠{T<:Real}(n::T, k::T) = factorial(n, n-k) |
|||
</syntaxhighlight> |
|||
'''Main''' |
|||
<syntaxhighlight lang="julia"> |
|||
function picknk{T<:Integer}(lo::T, hi::T) |
|||
n = rand(lo:hi) |
|||
k = rand(1:n) |
|||
return (n, k) |
|||
end |
|||
nsamp = 10 |
|||
print("Tests of the combinations (⊞) and permutations (⊠) operators for ") |
|||
println("integer values.") |
|||
println() |
|||
lo, hi = 1, 12 |
|||
print(nsamp, " samples of n ⊠ k with n in [", lo, ", ", hi, "] ") |
|||
println("and k in [1, n].") |
|||
for i in 1:nsamp |
|||
(n, k) = picknk(lo, hi) |
|||
println(@sprintf " %2d ⊠ %2d = %18d" n k n ⊠ k) |
|||
end |
|||
lo, hi = 10, 60 |
|||
println() |
|||
print(nsamp, " samples of n ⊞ k with n in [", lo, ", ", hi, "] ") |
|||
println("and k in [1, n].") |
|||
for i in 1:nsamp |
|||
(n, k) = picknk(lo, hi) |
|||
println(@sprintf " %2d ⊞ %2d = %18d" n k n ⊞ k) |
|||
end |
|||
println() |
|||
print("Tests of the combinations (⊞) and permutations (⊠) operators for ") |
|||
println("(big) float values.") |
|||
println() |
|||
lo, hi = 5, 15000 |
|||
print(nsamp, " samples of n ⊠ k with n in [", lo, ", ", hi, "] ") |
|||
println("and k in [1, n].") |
|||
for i in 1:nsamp |
|||
(n, k) = picknk(lo, hi) |
|||
n = BigFloat(n) |
|||
k = BigFloat(k) |
|||
println(@sprintf " %7.1f ⊠ %7.1f = %10.6e" n k n ⊠ k) |
|||
end |
|||
lo, hi = 100, 1000 |
|||
println() |
|||
print(nsamp, " samples of n ⊞ k with n in [", lo, ", ", hi, "] ") |
|||
println("and k in [1, n].") |
|||
for i in 1:nsamp |
|||
(n, k) = picknk(lo, hi) |
|||
n = BigFloat(n) |
|||
k = BigFloat(k) |
|||
println(@sprintf " %7.1f ⊞ %7.1f = %10.6e" n k n ⊞ k) |
|||
end |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Tests of the combinations (⊞) and permutations (⊠) operators for integer values. |
|||
10 samples of n ⊠ k with n in [1, 12] and k in [1, n]. |
|||
4 ⊠ 2 = 12 |
|||
9 ⊠ 2 = 72 |
|||
2 ⊠ 1 = 2 |
|||
8 ⊠ 2 = 56 |
|||
7 ⊠ 5 = 2520 |
|||
4 ⊠ 2 = 12 |
|||
9 ⊠ 8 = 362880 |
|||
11 ⊠ 6 = 332640 |
|||
1 ⊠ 1 = 1 |
|||
8 ⊠ 5 = 6720 |
|||
10 samples of n ⊞ k with n in [10, 60] and k in [1, n]. |
|||
58 ⊞ 26 = 22150361247847371 |
|||
22 ⊞ 21 = 22 |
|||
32 ⊞ 30 = 496 |
|||
11 ⊞ 4 = 330 |
|||
32 ⊞ 29 = 4960 |
|||
16 ⊞ 7 = 11440 |
|||
31 ⊞ 25 = 736281 |
|||
13 ⊞ 13 = 1 |
|||
43 ⊞ 28 = 151532656696 |
|||
49 ⊞ 37 = 92263734836 |
|||
Tests of the combinations (⊞) and permutations (⊠) operators for (big) float values. |
|||
10 samples of n ⊠ k with n in [5, 15000] and k in [1, n]. |
|||
8375.0 ⊠ 5578.0 = 2.200496e+20792 |
|||
1556.0 ⊠ 592.0 = 1.313059e+1833 |
|||
1234.0 ⊠ 910.0 = 2.231762e+2606 |
|||
12531.0 ⊠ 9361.0 = 2.339542e+36188 |
|||
12418.0 ⊠ 6119.0 = 1.049662e+24251 |
|||
9435.0 ⊠ 8960.0 = 4.273644e+32339 |
|||
9430.0 ⊠ 5385.0 = 1.471741e+20551 |
|||
9876.0 ⊠ 5386.0 = 9.073417e+20712 |
|||
941.0 ⊠ 911.0 = 8.689430e+2358 |
|||
8145.0 ⊠ 4357.0 = 1.368129e+16407 |
|||
10 samples of n ⊞ k with n in [100, 1000] and k in [1, n]. |
|||
757.0 ⊞ 237.0 = 6.813837e+202 |
|||
457.0 ⊞ 413.0 = 4.816707e+61 |
|||
493.0 ⊞ 372.0 = 8.607443e+117 |
|||
206.0 ⊞ 26.0 = 6.911828e+32 |
|||
432.0 ⊞ 300.0 = 1.248351e+114 |
|||
650.0 ⊞ 469.0 = 3.284854e+165 |
|||
203.0 ⊞ 115.0 = 1.198089e+59 |
|||
583.0 ⊞ 429.0 = 5.700279e+144 |
|||
329.0 ⊞ 34.0 = 2.225630e+46 |
|||
464.0 ⊞ 178.0 = 5.615925e+132 |
|||
</pre> |
|||
=={{header|Kotlin}}== |
|||
As Kotlin/JVM can use the java.math.BigInteger class, there is no need to use floating point approximations and so we use exact integer arithmetic for all parts of the task. |
|||
<syntaxhighlight lang="scala">// version 1.1.2 |
|||
import java.math.BigInteger |
|||
fun perm(n: Int, k: Int): BigInteger { |
|||
require(n > 0 && k >= 0) |
|||
return (n - k + 1 .. n).fold(BigInteger.ONE) { acc, i -> acc * BigInteger.valueOf(i.toLong()) } |
|||
} |
|||
fun comb(n: Int, k: Int): BigInteger { |
|||
require(n > 0 && k >= 0) |
|||
val fact = (2..k).fold(BigInteger.ONE) { acc, i -> acc * BigInteger.valueOf(i.toLong()) } |
|||
return perm(n, k) / fact |
|||
} |
|||
fun main(args: Array<String>) { |
|||
println("A sample of permutations from 1 to 12:") |
|||
for (n in 1..12) System.out.printf("%2d P %-2d = %d\n", n, n / 3, perm(n, n / 3)) |
|||
println("\nA sample of combinations from 10 to 60:") |
|||
for (n in 10..60 step 10) System.out.printf("%2d C %-2d = %d\n", n, n / 3, comb(n, n / 3)) |
|||
println("\nA sample of permutations from 5 to 15000:") |
|||
val na = intArrayOf(5, 50, 500, 1000, 5000, 15000) |
|||
for (n in na) { |
|||
val k = n / 3 |
|||
val s = perm(n, k).toString() |
|||
val l = s.length |
|||
val e = if (l <= 40) "" else "... (${l - 40} more digits)" |
|||
System.out.printf("%5d P %-4d = %s%s\n", n, k, s.take(40), e) |
|||
} |
|||
println("\nA sample of combinations from 100 to 1000:") |
|||
for (n in 100..1000 step 100) { |
|||
val k = n / 3 |
|||
val s = comb(n, k).toString() |
|||
val l = s.length |
|||
val e = if (l <= 40) "" else "... (${l - 40} more digits)" |
|||
System.out.printf("%4d C %-3d = %s%s\n", n, k, s.take(40), e) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A sample of permutations from 1 to 12: |
|||
1 P 0 = 1 |
|||
2 P 0 = 1 |
|||
3 P 1 = 3 |
|||
4 P 1 = 4 |
|||
5 P 1 = 5 |
|||
6 P 2 = 30 |
|||
7 P 2 = 42 |
|||
8 P 2 = 56 |
|||
9 P 3 = 504 |
|||
10 P 3 = 720 |
|||
11 P 3 = 990 |
|||
12 P 4 = 11880 |
|||
A sample of combinations from 10 to 60: |
|||
10 C 3 = 120 |
|||
20 C 6 = 38760 |
|||
30 C 10 = 30045015 |
|||
40 C 13 = 12033222880 |
|||
50 C 16 = 4923689695575 |
|||
60 C 20 = 4191844505805495 |
|||
A sample of permutations from 5 to 15000: |
|||
5 P 1 = 5 |
|||
50 P 16 = 103017324974226408345600000 |
|||
500 P 166 = 3534874921742942787609361826601762306844... (395 more digits) |
|||
1000 P 333 = 5969326288503415089039701765900784280998... (932 more digits) |
|||
5000 P 1666 = 6856745757255674275484536940248896062234... (5986 more digits) |
|||
15000 P 5000 = 9649853988727493922014858805931295980792... (20430 more digits) |
|||
A sample of combinations from 100 to 1000: |
|||
100 C 33 = 294692427022540894366527900 |
|||
200 C 66 = 7269752545169278341527066651192738976755... (14 more digits) |
|||
300 C 100 = 4158251463258564744783383526326405580280... (42 more digits) |
|||
400 C 133 = 1257948684182108702133348475651965004491... (70 more digits) |
|||
500 C 166 = 3926028386194422755220408345072331428197... (97 more digits) |
|||
600 C 200 = 2506017783221402805005616770513228835202... (125 more digits) |
|||
700 C 233 = 8103203563339599904740453644031138232944... (152 more digits) |
|||
800 C 266 = 2645623362683627034288829299556124255091... (180 more digits) |
|||
900 C 300 = 1743356373296446642960730765085718347630... (208 more digits) |
|||
1000 C 333 = 5776134553147651669777486323549601722339... (235 more digits) |
|||
</pre> |
|||
=={{header|Lua}}== |
|||
{{trans|Perl}} |
|||
<syntaxhighlight lang="Lua"> |
|||
-- Helper function to display results in scientific notation corrected |
|||
function eshow(x) |
|||
local e = math.floor(x / math.log(10)) |
|||
local exponentiated = math.exp(x - e * math.log(10)) |
|||
-- Corrected format specifier from %.8Fe%+d to %.8e, and manually constructing the scientific notation if needed |
|||
return string.format("%.8e", exponentiated) .. "e" .. tostring(e) |
|||
end |
|||
-- The rest of the functions remain the same |
|||
-- Define the factorial function for permutations |
|||
function P(n, k) |
|||
local x = 1 |
|||
for i = n - k + 1, n do |
|||
x = x * i |
|||
end |
|||
return x |
|||
end |
|||
-- Define the function for big permutations using logarithms |
|||
function P_big(n, k) |
|||
local x = 0 |
|||
for i = n - k + 1, n do |
|||
x = x + math.log(i) |
|||
end |
|||
return eshow(x) |
|||
end |
|||
-- Define the combinations function |
|||
function C(n, k) |
|||
local x = 1 |
|||
for i = 1, k do |
|||
x = x * (n - i + 1) / i |
|||
end |
|||
return x |
|||
end |
|||
-- Define the function for big combinations using logarithms |
|||
function C_big(n, k) |
|||
local x = 0 |
|||
for i = 1, k do |
|||
x = x + math.log(n - i + 1) - math.log(i) |
|||
end |
|||
return math.exp(x) |
|||
end |
|||
-- Function to showcase the calculations |
|||
function showoff(text, code, fname, ...) |
|||
local n = {...} |
|||
print("\nA sample of " .. text .. " from " .. n[1] .. " to " .. n[#n] .. "") |
|||
for _, v in ipairs(n) do |
|||
local k = math.floor(v / 3) |
|||
print(v, fname .. " " .. k .. " = ", code(v, k)) |
|||
end |
|||
end |
|||
-- Examples of usage |
|||
showoff("Permutations", P, "P", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) |
|||
showoff("Combinations", C, "C", 10, 20, 30, 40, 50, 60) |
|||
showoff("Permutations", P_big, "P", 5, 50, 500, 1000, 5000, 15000) |
|||
showoff("Combinations", C_big, "C", 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A sample of Permutations from 1 to 12 |
|||
1 P 0 = 1 |
|||
2 P 0 = 1 |
|||
3 P 1 = 3 |
|||
4 P 1 = 4 |
|||
5 P 1 = 5 |
|||
6 P 2 = 30 |
|||
7 P 2 = 42 |
|||
8 P 2 = 56 |
|||
9 P 3 = 504 |
|||
10 P 3 = 720 |
|||
11 P 3 = 990 |
|||
12 P 4 = 11880 |
|||
A sample of Combinations from 10 to 60 |
|||
10 C 3 = 120.0 |
|||
20 C 6 = 38760.0 |
|||
30 C 10 = 30045015.0 |
|||
40 C 13 = 12033222880.0 |
|||
50 C 16 = 4923689695575.0 |
|||
60 C 20 = 4.1918445058055e+15 |
|||
A sample of Permutations from 5 to 15000 |
|||
5 P 1 = 5.00000000e+00e0 |
|||
50 P 16 = 1.03017325e+00e26 |
|||
500 P 166 = 3.53487492e+00e434 |
|||
1000 P 333 = 5.96932629e+00e971 |
|||
5000 P 1666 = 6.85674576e+00e6025 |
|||
15000 P 5000 = 9.64985399e+00e20469 |
|||
A sample of Combinations from 100 to 1000 |
|||
100 C 33 = 2.9469242702254e+26 |
|||
200 C 66 = 7.2697525451696e+53 |
|||
300 C 100 = 4.158251463258e+81 |
|||
400 C 133 = 1.2579486841822e+109 |
|||
500 C 166 = 3.9260283861944e+136 |
|||
600 C 200 = 2.5060177832203e+164 |
|||
700 C 233 = 8.1032035633383e+191 |
|||
800 C 266 = 2.6456233626831e+219 |
|||
900 C 300 = 1.7433563732974e+247 |
|||
1000 C 333 = 5.776134553149e+274 |
|||
</pre> |
|||
=={{header|M2000 Interpreter}}== |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Module PermComb { |
|||
Form 80, 50 |
|||
perm=lambda (x,y) ->{ |
|||
def i,z |
|||
z=1 |
|||
For i=x-y+1 to x :z*=i:next i |
|||
=z |
|||
} |
|||
fact=lambda (x) ->{ |
|||
def i,z |
|||
z=1 |
|||
For i=2 to x :z*=i:next i |
|||
=z |
|||
} |
|||
comb=lambda (x as decimal, y as decimal) ->{ |
|||
If y>x then { |
|||
=0 |
|||
} else.if x=y then { |
|||
=1 |
|||
} else { |
|||
if x-y<y then y=x-y |
|||
def decimal i, z=1, ym |
|||
ym=y |
|||
For i=x to x-y+1 |
|||
z*=i |
|||
z=z/ym |
|||
ym-- : if ym<1 then ym=1@ |
|||
next i |
|||
=round(z,0) |
|||
} |
|||
} |
|||
Document Doc$ |
|||
WriteLn("-- Permutations - from 1 to 12") |
|||
For i=1 to 12 |
|||
l$="" : For j=1 to i : l$+= format$("P({0},{1})={2} ",i, j,perm(i, j)) :next j |
|||
Writetext(l$) |
|||
next i |
|||
WriteLn("-- Combinations from 10 to 60") |
|||
For i=10 to 60 step 10 |
|||
l$="" : For j=1 to i step i div 5 : l$+= format$("C({0},{1})={2} ",i, j,comb(i, j)) :next j |
|||
Writetext(l$) |
|||
Next i |
|||
WriteLn("-- Permutations from 5000 to 15000") |
|||
For i=5000 to 15000 step 5000 |
|||
l$="" : For j=10 to 70 step 20: l$+= format$("P({0},{1})={2} ",i, j,perm(i, j)) :next j |
|||
Writetext(l$) |
|||
Next i |
|||
WriteLn("-- Combinations from 200 to 1000") |
|||
For i=200 to 1000 step 200 |
|||
l$="" : For j=20 to 100 step 20: l$+= format$("C({0},{1})={2} ",i, j,comb(i, j)) :next j |
|||
Writetext(l$) |
|||
Next i |
|||
ClipBoard Doc$ |
|||
Sub WriteText(a$) |
|||
doc$=a$+{ |
|||
} |
|||
Report a$ |
|||
End Sub |
|||
Sub WriteLn(a$) |
|||
doc$=a$+{ |
|||
} |
|||
Print a$ |
|||
End Sub |
|||
} |
|||
PermComb |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
-- Permutations - from 1 to 12 |
|||
P(1,1)=1 |
|||
P(2,1)=2 P(2,2)=2 |
|||
P(3,1)=3 P(3,2)=6 P(3,3)=6 |
|||
P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 |
|||
P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 |
|||
P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 |
|||
P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 |
|||
P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 |
|||
P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 |
|||
P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 |
|||
P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 |
|||
P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 |
|||
-- Combinations from 10 to 60 |
|||
C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 |
|||
C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 |
|||
C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 |
|||
C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 |
|||
C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 |
|||
C(60,1)=60 C(60,13)=5166863427600 C(60,25)=51915437974328292 C(60,37)=23385332420868600 C(60,49)=342700125300 |
|||
-- Permutations from 5000 to 15000 |
|||
P(5000,10)=9,67807348145655E+36 P(5000,30)=8,53575581200676E+110 P(5000,50)=6,94616656703754E+184 P(5000,70)=5,21383580146195E+258 |
|||
P(10000,10)=9,95508690556325E+39 P(10000,30)=9,57391540294832E+119 P(10000,50)=8,84526658067387E+199 P(10000,70)=7,850079552152E+279 |
|||
P(15000,10)=5,74922667554068E+41 P(15000,30)=1,86266591363916E+125 P(15000,50)=5,87565776023335E+208 P(15000,70)=1,80450662858719E+292 |
|||
-- Combinations from 200 to 1000 |
|||
C(200,20)=1613587787967350073386147640 C(200,40)=721126811024990370 C(200,60)=286107190317772000463240955 C(200,80)=900482 C(200,100)=478205104 |
|||
C(400,20)=3558235073 C(400,40)=130321 C(400,60)=74780600187861332802765 C(400,80)=9521248771125 C(400,100)=447355513982663594791392 |
|||
C(600,20)=2801445153584 C(600,40)=266319106596345 C(600,60)=14409368913 C(600,80)=271441 C(600,100)=52868467287780595308 |
|||
C(800,20)=1925279023672620 C(800,40)=23121069591511231041 C(800,60)=18702067923763447158 C(800,80)=1193559552292625 C(800,100)=172727802 |
|||
C(1000,20)=1239329180287869852 C(1000,40)=1937726921514640866484017 C(1000,60)=149470629867337347460963500 C(1000,80)=1269150275532146867313740 C(1000,100)=10088410532027029794548 |
|||
=={{header|Maple}}== |
|||
<syntaxhighlight lang="maple"> |
|||
comb := proc (n::integer, k::integer) |
|||
return factorial(n)/(factorial(k)*factorial(n-k)); |
|||
end proc; |
|||
perm := proc (n::integer, k::integer) |
|||
return factorial(n)/factorial(n-k); |
|||
end proc; |
|||
</syntaxhighlight> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">ClearAll[Combination,Permutation] |
|||
Combination[n_,k_]:=Binomial[n,k] |
|||
Permutation[n_,k_]:=Binomial[n,k]k! |
|||
TableForm[Array[Permutation,{12,12}],TableHeadings->{Range[12],Range[12]}] |
|||
TableForm[Array[Combination,{6,6},{{10,60},{10,60}}],TableHeadings->{Range[10,60,10],Range[10,60,10]}] |
|||
{Row[{#,"P",#-2}," "],N@Permutation[#,#-2]}&/@{5,1000,5000,10000,15000}//Grid |
|||
{Row[{#,"C",#/2}," "],N@Combination[#,#/2]}&/@Range[100,1000,100]//Grid</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 2 3 4 5 6 7 8 9 10 11 12 |
|||
1 1 0 0 0 0 0 0 0 0 0 0 0 |
|||
2 2 2 0 0 0 0 0 0 0 0 0 0 |
|||
3 3 6 6 0 0 0 0 0 0 0 0 0 |
|||
4 4 12 24 24 0 0 0 0 0 0 0 0 |
|||
5 5 20 60 120 120 0 0 0 0 0 0 0 |
|||
6 6 30 120 360 720 720 0 0 0 0 0 0 |
|||
7 7 42 210 840 2520 5040 5040 0 0 0 0 0 |
|||
8 8 56 336 1680 6720 20160 40320 40320 0 0 0 0 |
|||
9 9 72 504 3024 15120 60480 181440 362880 362880 0 0 0 |
|||
10 10 90 720 5040 30240 151200 604800 1814400 3628800 3628800 0 0 |
|||
11 11 110 990 7920 55440 332640 1663200 6652800 19958400 39916800 39916800 0 |
|||
12 12 132 1320 11880 95040 665280 3991680 19958400 79833600 239500800 479001600 479001600 |
|||
10 20 30 40 50 60 |
|||
10 1 0 0 0 0 0 |
|||
20 184756 1 0 0 0 0 |
|||
30 30045015 30045015 1 0 0 0 |
|||
40 847660528 137846528820 847660528 1 0 0 |
|||
50 10272278170 47129212243960 47129212243960 10272278170 1 0 |
|||
60 75394027566 4191844505805495 118264581564861424 4191844505805495 75394027566 1 |
|||
5 P 3 60. |
|||
1000 P 998 2.011936300385469*10^2567 |
|||
5000 P 4998 2.114288963302772*10^16325 |
|||
10000 P 9998 1.423129840458527*10^35659 |
|||
15000 P 14998 1.373299516742584*10^56129 |
|||
100 C 50 1.00891*10^29 |
|||
200 C 100 9.05485*10^58 |
|||
300 C 150 9.37597*10^88 |
|||
400 C 200 1.02953*10^119 |
|||
500 C 250 1.16744*10^149 |
|||
600 C 300 1.35108*10^179 |
|||
700 C 350 1.58574*10^209 |
|||
800 C 400 1.88042*10^239 |
|||
900 C 450 2.24747*10^269 |
|||
1000 C 500 2.70288*10^299 |
|||
</pre> |
|||
Note that Mathematica can easily handle very big numbers with exact integer arithmetic: |
|||
<syntaxhighlight lang="mathematica"> |
|||
Permutation[200000, 100000] |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
The output is 516777 digits longs: |
|||
<pre> |
|||
50287180689616781338617355322585606........0321815299686400000000000000000000......(lots of zeroes) |
|||
</pre> |
|||
=={{header|МК-61/52}}== |
|||
<syntaxhighlight lang="text">П2 <-> П1 -> <-> П7 КПП7 С/П |
|||
ИП1 ИП2 - ПП 53 П3 ИП1 ПП 53 ИП3 / В/О |
|||
1 ИП1 * L2 21 В/О |
|||
ИП1 ИП2 - ПП 53 П3 ИП2 ПП 53 ИП3 * П3 ИП1 ПП 53 ИП3 / В/О |
|||
ИП1 ИП2 + 1 - П1 ПП 26 В/О |
|||
ВП П0 1 ИП0 * L0 56 В/О</syntaxhighlight> |
|||
''Input'': ''x ^ n ^ k В/О С/П'', where ''x'' = 8 for permutations; 20 for permutations with repetitions; 26 for combinations; 44 for combinations with repetitions. |
|||
Printing of test cases is performed incrementally, which is associated with the characteristics of the device output. |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="nim">import bigints |
|||
proc perm(n, k: int32): BigInt = |
|||
result = initBigInt 1 |
|||
var |
|||
k = n - k |
|||
n = n |
|||
while n > k: |
|||
result *= n |
|||
dec n |
|||
proc comb(n, k: int32): BigInt = |
|||
result = perm(n, k) |
|||
var k = k |
|||
while k > 0: |
|||
result = result div k |
|||
dec k |
|||
echo "P(1000, 969) = ", perm(1000, 969) |
|||
echo "C(1000, 969) = ", comb(1000, 969)</syntaxhighlight> |
|||
=={{header|PARI/GP}}== |
|||
<syntaxhighlight lang="parigp">sample(f,a,b)=for(i=1,4, my(n1=random(b-a)+a,n2=random(b-a)+a); [n1,n2]=[max(n1,n2),min(n1,n2)]; print(n1", "n2": "f(n1,n2))) |
|||
permExact(m,n)=factorback([m-n+1..m]); |
|||
combExact=binomial; |
|||
permApprox(m,n)=exp(lngamma(m+1)-lngamma(m-n+1)); |
|||
combApprox(m,n)=exp(lngamma(m+1)-lngamma(n+1)-lngamma(m-n+1)); |
|||
sample(permExact, 1, 12); |
|||
sample(combExact, 10, 60); |
|||
sample(permApprox, 5, 15000); |
|||
sample(combApprox, 100, 1000);</syntaxhighlight> |
|||
{{out}} |
|||
<pre>?sample(permExact, 1, 12); |
|||
8, 2: 56 |
|||
11, 8: 6652800 |
|||
9, 9: 362880 |
|||
6, 1: 6 |
|||
?sample(combExact, 10, 60); |
|||
46, 14: 239877544005 |
|||
34, 22: 548354040 |
|||
51, 20: 77535155627160 |
|||
49, 26: 58343356817424 |
|||
?sample(permApprox, 5, 15000); |
|||
8374, 8306: 6.6786635386843773562533982329356314192 E29119 |
|||
4064, 2497: 7.7325589445068984950461595444827041944 E8575 |
|||
13234, 784: 1.3439405881429921844444755481930625437 E3221 |
|||
14136, 1523: 9.7219281356264565060667995087812528666 E6283 |
|||
?sample(combApprox, 100, 1000); |
|||
988, 702: 4.1430346142101709187524161097370204275 E256 |
|||
861, 225: 1.9423942269910057792279495652023745087 E213 |
|||
580, 350: 4.9721729266474994835623000459244303642 E167 |
|||
977, 846: 6.0586575447000334467351859308510379521 E165</pre> |
|||
=={{header|Perl}}== |
|||
Although Perl can handle arbitrarily large numbers using Math::BigInt and Math::BigFloat, it's |
|||
native integers and floats are limited to what the computer's native types can handle. |
|||
As with the Raku code, some special handling was done for those values which would have overflowed the native floating point type. |
|||
<syntaxhighlight lang="perl">use strict; |
|||
use warnings; |
|||
showoff( "Permutations", \&P, "P", 1 .. 12 ); |
|||
showoff( "Combinations", \&C, "C", map $_*10, 1..6 ); |
|||
showoff( "Permutations", \&P_big, "P", 5, 50, 500, 1000, 5000, 15000 ); |
|||
showoff( "Combinations", \&C_big, "C", map $_*100, 1..10 ); |
|||
sub showoff { |
|||
my ($text, $code, $fname, @n) = @_; |
|||
print "\nA sample of $text from $n[0] to $n[-1]\n"; |
|||
for my $n ( @n ) { |
|||
my $k = int( $n / 3 ); |
|||
print $n, " $fname $k = ", $code->($n, $k), "\n"; |
|||
} |
|||
} |
|||
sub P { |
|||
my ($n, $k) = @_; |
|||
my $x = 1; |
|||
$x *= $_ for $n - $k + 1 .. $n ; |
|||
$x; |
|||
} |
|||
sub P_big { |
|||
my ($n, $k) = @_; |
|||
my $x = 0; |
|||
$x += log($_) for $n - $k + 1 .. $n ; |
|||
eshow($x); |
|||
} |
|||
sub C { |
|||
my ($n, $k) = @_; |
|||
my $x = 1; |
|||
$x *= ($n - $_ + 1) / $_ for 1 .. $k; |
|||
$x; |
|||
} |
|||
sub C_big { |
|||
my ($n, $k) = @_; |
|||
my $x = 0; |
|||
$x += log($n - $_ + 1) - log($_) for 1 .. $k; |
|||
exp($x); |
|||
} |
|||
sub eshow { |
|||
my ($x) = @_; |
|||
my $e = int( $x / log(10) ); |
|||
sprintf "%.8Fe%+d", exp($x - $e * log(10)), $e; |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:50ex">A sample of Permutations from 1 to 12 |
|||
1 P 0 = 1 |
|||
2 P 0 = 1 |
|||
3 P 1 = 3 |
|||
4 P 1 = 4 |
|||
5 P 1 = 5 |
|||
6 P 2 = 30 |
|||
7 P 2 = 42 |
|||
8 P 2 = 56 |
|||
9 P 3 = 504 |
|||
10 P 3 = 720 |
|||
11 P 3 = 990 |
|||
12 P 4 = 11880 |
|||
A sample of Combinations from 10 to 60 |
|||
10 C 3 = 120 |
|||
20 C 6 = 38760 |
|||
30 C 10 = 30045015 |
|||
40 C 13 = 12033222880 |
|||
50 C 16 = 4923689695575 |
|||
60 C 20 = 4.1918445058055e+15 |
|||
A sample of Permutations from 5 to 15000 |
|||
5 P 1 = 5.00000000e+0 |
|||
50 P 16 = 1.03017325e+26 |
|||
500 P 166 = 3.53487492e+434 |
|||
1000 P 333 = 5.96932629e+971 |
|||
5000 P 1666 = 6.85674576e+6025 |
|||
15000 P 5000 = 9.64985399e+20469 |
|||
A sample of Combinations from 100 to 1000 |
|||
100 C 33 = 2.94692427022544e+26 |
|||
200 C 66 = 7.26975254516929e+53 |
|||
300 C 100 = 4.15825146325788e+81 |
|||
400 C 133 = 1.25794868418216e+109 |
|||
500 C 166 = 3.92602838619369e+136 |
|||
600 C 200 = 2.50601778322159e+164 |
|||
700 C 233 = 8.10320356333741e+191 |
|||
800 C 266 = 2.64562336268385e+219 |
|||
900 C 300 = 1.74335637329697e+247 |
|||
1000 C 333 = 5.77613455314442e+274</pre> |
|||
=={{header|Phix}}== |
|||
Translation of Raku/Sidef, same results<br> |
|||
Update: there are now builtin routines k_perm(n,k) and choose(n,k), slightly more efficient equivalents of P() and C() respectively. |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">P</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)/</span><span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">P</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)/</span><span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">lstirling</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">10</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">lstirling</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: #7060A8;">log</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: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #004600;">E</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/(</span><span style="color: #000000;">12</span><span style="color: #0000FF;">*</span><span style="color: #004600;">E</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">P_approx</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">lstirling</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">lstirling</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">C_approx</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">lstirling</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">lstirling</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">lstirling</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">to_s</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">/</span><span style="color: #7060A8;">log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%.9ge%d"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #004600;">E</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">-</span><span style="color: #000000;">e</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #000080;font-style:italic;">-- Test code</span> |
|||
<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;">"=> Exact results:\n"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<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;">"P(%d,%d) = %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">P</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">10</span> <span style="color: #008080;">to</span> <span style="color: #000000;">60</span> <span style="color: #008080;">by</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<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;">"C(%d,%d) = %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">C</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<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;">"=> Floating point approximations:\n"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">500</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1000</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5000</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15000</span><span style="color: #0000FF;">}</span> |
|||
<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: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<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;">"P(%d,%d) = %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">to_s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">P_approx</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">))})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">100</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1000</span> <span style="color: #008080;">by</span> <span style="color: #000000;">100</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<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;">"C(%d,%d) = %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">to_s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C_approx</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">))})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
=> Exact results: |
|||
P(1,0) = 1 |
|||
P(2,0) = 1 |
|||
P(3,1) = 3 |
|||
P(4,1) = 4 |
|||
P(5,1) = 5 |
|||
P(6,2) = 30 |
|||
P(7,2) = 42 |
|||
P(8,2) = 56 |
|||
P(9,3) = 504 |
|||
P(10,3) = 720 |
|||
P(11,3) = 990 |
|||
P(12,4) = 11880 |
|||
C(10,3) = 120 |
|||
C(20,6) = 38760 |
|||
C(30,10) = 30045014 |
|||
C(40,13) = 12033222880 |
|||
C(50,16) = 4923689695575 |
|||
C(60,20) = 4191844505805496 |
|||
=> Floating point approximations: |
|||
P(5,1) = 5e0 |
|||
P(50,16) = 1.03017326e26 |
|||
P(500,166) = 3.53487492e434 |
|||
P(1000,333) = 5.96932629e971 |
|||
P(5000,1666) = 6.85674576e6025 |
|||
P(15000,5000) = 9.64985399e20469 |
|||
C(100,33) = 2.94692433e26 |
|||
C(200,66) = 7.26975256e53 |
|||
C(300,100) = 4.15825147e81 |
|||
C(400,133) = 1.25794868e109 |
|||
C(500,166) = 3.92602839e136 |
|||
C(600,200) = 2.50601778e164 |
|||
C(700,233) = 8.10320356e191 |
|||
C(800,266) = 2.64562336e219 |
|||
C(900,300) = 1.74335637e247 |
|||
C(1000,333) = 5.77613455e274 |
|||
</pre> |
|||
=={{header|Python}}== |
|||
==={{libheader|SciPy}}=== |
|||
<syntaxhighlight lang="python">from __future__ import print_function |
|||
from scipy.misc import factorial as fact |
|||
from scipy.misc import comb |
|||
def perm(N, k, exact=0): |
|||
return comb(N, k, exact) * fact(k, exact) |
|||
exact=True |
|||
print('Sample Perms 1..12') |
|||
for N in range(1, 13): |
|||
k = max(N-2, 1) |
|||
print('%iP%i =' % (N, k), perm(N, k, exact), end=', ' if N % 5 else '\n') |
|||
print('\n\nSample Combs 10..60') |
|||
for N in range(10, 61, 10): |
|||
k = N-2 |
|||
print('%iC%i =' % (N, k), comb(N, k, exact), end=', ' if N % 50 else '\n') |
|||
exact=False |
|||
print('\n\nSample Perms 5..1500 Using FP approximations') |
|||
for N in [5, 15, 150, 1500, 15000]: |
|||
k = N-2 |
|||
print('%iP%i =' % (N, k), perm(N, k, exact)) |
|||
print('\nSample Combs 100..1000 Using FP approximations') |
|||
for N in range(100, 1001, 100): |
|||
k = N-2 |
|||
print('%iC%i =' % (N, k), comb(N, k, exact)) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Sample Perms 1..12 |
|||
1P1 = 1, 2P1 = 2, 3P1 = 3, 4P2 = 12, 5P3 = 60 |
|||
6P4 = 360, 7P5 = 2520, 8P6 = 20160, 9P7 = 181440, 10P8 = 1814400 |
|||
11P9 = 19958400, 12P10 = 239500800, |
|||
Sample Combs 10..60 |
|||
10C8 = 45, 20C18 = 190, 30C28 = 435, 40C38 = 780, 50C48 = 1225 |
|||
60C58 = 1770, |
|||
Sample Perms 5..1500 Using FP approximations |
|||
5P3 = 60.0 |
|||
15P13 = 653837184000.0 |
|||
150P148 = 2.85669197822e+262 |
|||
1500P1498 = inf |
|||
15000P14998 = inf |
|||
Sample Combs 100..1000 Using FP approximations |
|||
100C98 = 4950.0 |
|||
200C198 = 19900.0 |
|||
300C298 = 44850.0 |
|||
400C398 = 79800.0 |
|||
500C498 = 124750.0 |
|||
600C598 = 179700.0 |
|||
700C698 = 244650.0 |
|||
800C798 = 319600.0 |
|||
900C898 = 404550.0 |
|||
1000C998 = 499500.0</pre> |
|||
=={{header|R}}== |
|||
R has most of this built in. The documentation for choose warns that it only calculates its result directly if k is small. Skimming [https://github.com/wch/r-source/blob/trunk/src/nmath/choose.c what appears to be the source code] suggests that 29 is the highest "small" k. This means that we can solve both tasks with little more than R's choose. |
|||
<syntaxhighlight lang="rsplus">perm <- function(n, k) choose(n, k) * factorial(k) |
|||
print(perm(seq(from = 3, to = 12, by = 3), seq(from = 2, to = 8, by = 2))) |
|||
print(choose(seq(from = 10, to = 60, by = 10), seq(from = 3, to = 18, by = 3))) |
|||
print(perm(seq(from = 1500, to = 15000, by = 1500), seq(from = 55, to = 100, by = 5))) |
|||
print(choose(seq(from = 100, to = 1000, by = 150), seq(from = 70, to = 100, by = 5)))</syntaxhighlight> |
|||
{{out}} |
|||
<pre>> print(perm(seq(from = 3, to = 12, by = 3), seq(from = 2, to = 8, by = 2))) |
|||
[1] 6 360 60480 19958400 |
|||
> print(choose(seq(from = 10, to = 60, by = 10), seq(from = 3, to = 18, by = 3))) |
|||
[1] 1.200000e+02 3.876000e+04 1.430715e+07 5.586853e+09 2.250830e+12 9.250296e+14 |
|||
> print(perm(seq(from = 1500, to = 15000, by = 1500), seq(from = 55, to = 100, by = 5))) |
|||
[1] 1.777313e+174 2.340618e+208 1.807619e+237 1.972900e+264 2.940161e+290 Inf Inf Inf Inf Inf |
|||
> print(choose(seq(from = 100, to = 1000, by = 150), seq(from = 70, to = 100, by = 5))) |
|||
[1] 2.937234e+25 1.158870e+65 4.228142e+85 3.202323e+101 1.944760e+115 8.124447e+127 6.385051e+139</pre> |
|||
We can notice some interesting things about R from this task. Despite being a mathematical programming language: |
|||
#R does not have any function like perm built in. |
|||
#R does not have big integers by default and will return Inf without warning. |
|||
#R's documentation does not tell us exactly when choose's behaviour changes. |
|||
=={{header|Racket}}== |
|||
Racket's "math" library has two functions that compute nCk and nPk. |
|||
They work only on integers, but since Racket supports unlimited integers |
|||
there is no need for a floating point estimate: |
|||
<syntaxhighlight lang="racket"> |
|||
#lang racket |
|||
(require math) |
|||
(define C binomial) |
|||
(define P permutations) |
|||
(C 1000 10) ; -> 263409560461970212832400 |
|||
(P 1000 10) ; -> 955860613004397508326213120000 |
|||
</syntaxhighlight> |
|||
(I'll spare this page from yet another big listing of samples...) |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
Raku can't compute arbitrary large floating point values, thus we will use logarithms, as is often needed when dealing with combinations. We'll also use a Stirling method to approximate <math>\ln(n!)</math>: |
|||
<math>\ln n! \approx |
|||
\frac{1}{2}\ln(2\pi n) + n\ln\left(\frac{n}{e} + \frac{1}{12 e n}\right)</math> |
|||
Notice that Raku can process arbitrary long integers, though. So it's not clear whether using floating points is useful in this case. |
|||
<syntaxhighlight lang="raku" line>multi P($n, $k) { [*] $n - $k + 1 .. $n } |
|||
multi C($n, $k) { P($n, $k) / [*] 1 .. $k } |
|||
sub lstirling(\n) { |
|||
n < 10 ?? lstirling(n+1) - log(n+1) !! |
|||
.5*log(2*pi*n)+ n*log(n/e+1/(12*e*n)) |
|||
} |
|||
role Logarithm { |
|||
method gist { |
|||
my $e = (self/10.log).Int; |
|||
sprintf "%.8fE%+d", exp(self - $e*10.log), $e; |
|||
} |
|||
} |
|||
multi P($n, $k, :$float!) { |
|||
(lstirling($n) - lstirling($n -$k)) |
|||
but Logarithm |
|||
} |
|||
multi C($n, $k, :$float!) { |
|||
(lstirling($n) - lstirling($n -$k) - lstirling($k)) |
|||
but Logarithm |
|||
} |
|||
say "Exact results:"; |
|||
for 1..12 -> $n { |
|||
my $p = $n div 3; |
|||
say "P($n, $p) = ", P($n, $p); |
|||
} |
|||
for 10, 20 ... 60 -> $n { |
|||
my $p = $n div 3; |
|||
say "C($n, $p) = ", C($n, $p); |
|||
} |
|||
say ''; |
|||
say "Floating point approximations:"; |
|||
for 5, 50, 500, 1000, 5000, 15000 -> $n { |
|||
my $p = $n div 3; |
|||
say "P($n, $p) = ", P($n, $p, :float); |
|||
} |
|||
for 100, 200 ... 1000 -> $n { |
|||
my $p = $n div 3; |
|||
say "C($n, $p) = ", C($n, $p, :float); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Exact results: |
|||
P(1, 0) = 1 |
|||
P(2, 0) = 1 |
|||
P(3, 1) = 3 |
|||
P(4, 1) = 4 |
|||
P(5, 1) = 5 |
|||
P(6, 2) = 30 |
|||
P(7, 2) = 42 |
|||
P(8, 2) = 56 |
|||
P(9, 3) = 504 |
|||
P(10, 3) = 720 |
|||
P(11, 3) = 990 |
|||
P(12, 4) = 11880 |
|||
C(10, 3) = 120 |
|||
C(20, 6) = 38760 |
|||
C(30, 10) = 30045015 |
|||
C(40, 13) = 12033222880 |
|||
C(50, 16) = 4923689695575 |
|||
C(60, 20) = 4191844505805495 |
|||
Floating point approximations: |
|||
P(5, 1) = 5.00000000E+0 |
|||
P(50, 16) = 1.03017326E+26 |
|||
P(500, 166) = 3.53487492E+434 |
|||
P(1000, 333) = 5.96932629E+971 |
|||
P(5000, 1666) = 6.85674576E+6025 |
|||
P(15000, 5000) = 9.64985399E+20469 |
|||
C(100, 33) = 2.94692433E+26 |
|||
C(200, 66) = 7.26975256E+53 |
|||
C(300, 100) = 4.15825147E+81 |
|||
C(400, 133) = 1.25794868E+109 |
|||
C(500, 166) = 3.92602839E+136 |
|||
C(600, 200) = 2.50601778E+164 |
|||
C(700, 233) = 8.10320356E+191 |
|||
C(800, 266) = 2.64562336E+219 |
|||
C(900, 300) = 1.74335637E+247 |
|||
C(1000, 333) = 5.77613455E+274</pre> |
|||
=={{header|REXX}}== |
|||
The hard part of this REXX program was coding the '''DO''' loops for the various ranges. |
|||
<syntaxhighlight lang="rexx">/*REXX program compute and displays a sampling of combinations and permutations. */ |
|||
numeric digits 100 /*use 100 decimal digits of precision. */ |
|||
do j=1 for 12; _= /*show all permutations from 1 ──► 12.*/ |
|||
do k=1 for j /*step through all J permutations. */ |
|||
_=_ 'P('j","k')='perm(j,k)" " /*add an extra blank between numbers. */ |
|||
end /*k*/ |
|||
say strip(_) /*show the permutations horizontally. */ |
|||
end /*j*/ |
|||
say /*display a blank line for readability.*/ |
|||
do j=10 to 60 by 10; _= /*show some combinations 10 ──► 60. */ |
|||
do k= 1 to j by j%5 /*step through some combinations. */ |
|||
_=_ 'C('j","k')='comb(j,k)" " /*add an extra blank between numbers. */ |
|||
end /*k*/ |
|||
say strip(_) /*show the combinations horizontally. */ |
|||
end /*j*/ |
|||
say /*display a blank line for readability.*/ |
|||
numeric digits 20 /*force floating point for big numbers.*/ |
|||
do j=5 to 15000 by 1000; _= /*show a few permutations, big numbers.*/ |
|||
do k=1 to j for 5 by j%10 /*step through some J permutations. */ |
|||
_=_ 'P('j","k')='perm(j,k)" " /*add an extra blank between numbers. */ |
|||
end /*k*/ |
|||
say strip(_) /*show the permutations horizontally. */ |
|||
end /*j*/ |
|||
say /*display a blank line for readability.*/ |
|||
do j=100 to 1000 by 100; _= /*show a few combinations, big numbers.*/ |
|||
do k= 1 to j by j%5 /*step through some combinations. */ |
|||
_=_ 'C('j","k')='comb(j,k)" " /*add an extra blank between numbers. */ |
|||
end /*k*/ |
|||
say strip(_) /*show the combinations horizontally. */ |
|||
end /*j*/ |
|||
exit /*stick a fork in it, we're all done. */ |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
perm: procedure; parse arg x,y; call .combPerm; return _ |
|||
.combPerm: _=1; do j=x-y+1 to x; _=_*j; end; return _ |
|||
!: procedure; parse arg x; !=1; do j=2 to x; !=!*j; end; return ! |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
comb: procedure; parse arg x,y /*arguments: X things, Y at-a-time.*/ |
|||
if y >x then return 0 /*oops-say, an error, too big a chunk.*/ |
|||
if x =y then return 1 /*X things are the same as chunk size.*/ |
|||
if x-y <y then y=x - y /*switch things around for speed. */ |
|||
call .combPerm /*call subroutine to do heavy lifting. */ |
|||
return _ / !(y) /*just perform one last division. */</syntaxhighlight> |
|||
'''output''' |
|||
<pre> |
|||
P(1,1)=1 |
|||
P(2,1)=2 P(2,2)=2 |
|||
P(3,1)=3 P(3,2)=6 P(3,3)=6 |
|||
P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 |
|||
P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 |
|||
P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 |
|||
P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 |
|||
P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 |
|||
P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 |
|||
P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 |
|||
P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 |
|||
P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 |
|||
C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 |
|||
C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 |
|||
C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 |
|||
C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 |
|||
C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 |
|||
C(60,1)=60 C(60,13)=5166863427600 C(60,25)=51915437974328292 C(60,37)=23385332420868600 C(60,49)=342700125300 |
|||
P(5,1)=5 P(5,1)=5 P(5,1)=5 P(5,1)=5 P(5,1)=5 |
|||
P(1005,1)=1005 P(1005,101)=9.1176524923776877363E+300 P(1005,201)=1.2772738260896333926E+594 P(1005,301)=6.9244021230613662196E+881 P(1005,401)=2.4492580742838357278E+1163 |
|||
P(2005,1)=2005 P(2005,201)=1.6533543480914610058E+659 P(2005,401)=3.0753126526205309249E+1305 P(2005,601)=7.9852540678709597130E+1940 P(2005,801)=8.0516979630356802995E+2563 |
|||
P(3005,1)=3005 P(3005,301)=1.1935689764209015622E+1040 P(3005,601)=1.5619600532077469150E+2062 P(3005,901)=1.0291767405881430479E+3068 P(3005,1201)=1.5669988662999668720E+4055 |
|||
P(4005,1)=4005 P(4005,401)=4.3808609526948101266E+1435 P(4005,801)=2.3060742016678396933E+2848 P(4005,1201)=2.2044072986703009755E+4239 P(4005,1601)=2.8973897505902543204E+5605 |
|||
P(5005,1)=5005 P(5005,501)=1.4180262672357809801E+1842 P(5005,1001)=2.8239356430641573722E+3656 P(5005,1501)=3.6832518654277810594E+5443 P(5005,2001)=3.9303728189857603162E+7199 |
|||
P(6005,1)=6005 P(6005,601)=2.4482219222979658097E+2257 P(6005,1201)=1.0247320583108167487E+4482 P(6005,1801)=1.0131515875595211375E+6674 P(6005,2401)=4.8762853043004294329E+8828 |
|||
P(7005,1)=7005 P(7005,701)=7.6900396347210828241E+2679 P(7005,1401)=1.2659048848290269952E+5322 P(7005,2101)=1.7753130713788487191E+7926 P(7005,2801)=7.2114365718218704695E+10486 |
|||
P(8005,1)=8005 P(8005,801)=3.9769062582658855959E+3108 P(8005,1601)=4.3272401446508603181E+6174 P(8005,2401)=1.4466844005282015778E+9197 P(8005,3201)=8.3354759867215982278E+12169 |
|||
P(9005,1)=9005 P(9005,901)=5.6135384805755901099E+3542 P(9005,1801)=1.1194389175552115248E+7038 P(9005,2701)=2.4737530806300682806E+10484 P(9005,3601)=5.6056491332873455398E+13874 |
|||
P(10005,1)=10005 P(10005,1001)=5.3580936683833889197E+3981 P(10005,2001)=1.3407350644082770778E+7911 P(10005,3001)=1.3407953461588097193E+11786 P(10005,4001)=8.1811569565040010437E+15598 |
|||
P(11005,1)=11005 P(11005,1101)=1.1340564277915775963E+4425 P(11005,2201)=7.9753039151558717610E+8792 P(11005,3301)=8.0842724022079710248E+13100 P(11005,4401)=2.9749926937463675736E+17340 |
|||
P(12005,1)=12005 P(12005,1201)=2.1391703159775094656E+4872 P(12005,2401)=3.7994859265471124812E+9682 P(12005,3601)=3.5081603331307865953E+14427 P(12005,4801)=6.9968644993020337359E+19097 |
|||
P(13005,1)=13005 P(13005,1301)=1.6832659142209713962E+5323 P(13005,2601)=3.1719005022749408296E+10579 P(13005,3901)=1.1206120643200361213E+15765 P(13005,5201)=5.0883658993886790178E+20869 |
|||
P(14005,1)=14005 P(14005,1401)=2.9074578200382556975E+5777 P(14005,2801)=1.2835011192416517281E+11483 P(14005,4201)=3.8312600202917546343E+17112 P(14005,5601)=8.7456467698123057261E+22654 |
|||
C(100,1)=100 C(100,21)=2.0418414110621321255E+21 C(100,41)=2.0116440213369968048E+28 C(100,61)=9.0139240300346304925E+27 C(100,81)=1.3234157293921226741E+20 |
|||
C(200,1)=200 C(200,41)=8.0006165666286406037E+42 C(200,81)=2.4404128184470558197E+57 C(200,121)=1.0891098528606695394E+57 C(200,161)=5.0935602365182339252E+41 |
|||
C(300,1)=300 C(300,61)=3.5574671252567510894E+64 C(300,121)=3.3878557197772169409E+86 C(300,181)=1.5098730832156289128E+86 C(300,241)=2.2510943427454545270E+63 |
|||
C(400,1)=400 C(400,81)=1.6703771503944415835E+86 C(400,161)=4.9770797199515347150E+115 C(400,241)=2.2166247162163128334E+115 C(400,321)=1.0537425948749981954E+85 |
|||
C(500,1)=500 C(500,101)=8.0859177660929770887E+107 C(500,201)=7.5447012685604958486E+144 C(500,301)=3.3587706644089915087E+144 C(500,401)=5.0915068227892187414E+106 |
|||
C(600,1)=600 C(600,121)=3.9913554739811382543E+129 C(600,241)=1.1667430218545073615E+174 C(600,361)=5.1927067085306791157E+173 C(600,481)=2.5101559893540422495E+128 |
|||
C(700,1)=700 C(700,141)=1.9971304197729039382E+151 C(700,281)=1.8294137562513979560E+203 C(700,421)=8.1403842518866639077E+202 C(700,561)=1.2548814134936695871E+150 |
|||
C(800,1)=800 C(800,161)=1.0093242166331589874E+173 C(800,321)=2.8977104736455704539E+232 C(800,481)=1.2892100651978213666E+232 C(800,641)=6.3378002682503352943E+171 |
|||
C(900,1)=900 C(900,181)=5.1402207737939392620E+194 C(900,361)=4.6256239559539226532E+261 C(900,541)=2.0577328996911473555E+261 C(900,721)=3.2260054093505652100E+193 |
|||
C(1000,1)=1000 C(1000,201)=2.6336937554862900107E+216 C(1000,401)=7.4293352412781479131E+290 C(1000,601)=3.3046738011675400053E+290 C(1000,801)=1.6522236106515115238E+215 |
|||
</pre> |
|||
=={{header|RPL}}== |
|||
≪ / LAST ROT * - ≫ '<span style="color:blue">BMOD</span>' STO |
|||
≪ → n k |
|||
≪ # 1d |
|||
n k - 1 + n '''FOR''' j |
|||
j * '''NEXT''' |
|||
≫ ≫ '<span style="color:blue">BPERM</span>' STO |
|||
≪ → n k |
|||
≪ # 1d |
|||
DUP n k - 1 + n '''FOR''' j |
|||
j * |
|||
'''WHILE''' DUP2 SWAP <span style="color:blue">BMOD</span> # 0d == 3 PICK k R→B ≤ AND '''REPEAT''' |
|||
OVER / SWAP 1 + SWAP '''END''' |
|||
'''NEXT''' SWAP DROP |
|||
≫ ≫ '<span style="color:blue">BCOMB</span>' STO |
|||
To mitigate risk of data overflow with 64-bits integers, the inner <code>WHILE..REPEAT</code> loop permanently attempts to divide the current numerator by increasing values of k. |
|||
≪ {} 1 11 '''FOR''' j 12 j <span style="color:blue">BPERM</span> + '''NEXT''' ≫ |
|||
≪ {} 10 50 '''FOR''' j 60 j <span style="color:blue">BCOMB</span> + 10 '''STEP''' ≫ |
|||
{{out}} |
|||
<pre> |
|||
2: { # 12d # 132d # 1320d # 11880d # 95040d # 665280d # 3991680d # 19958400d # 79833600d # 239500800d # 479001600d } |
|||
1: { # 75394027566d # 4191844505805495d # 118264581564861424d # 4191844505805495d # 75394027566d } |
|||
</pre> |
|||
Floating point approximations can be obtained by the built-in commands, provided that the result does not go beyond 1E500: |
|||
1000 150 PERM |
|||
1000 400 COMB |
|||
{{out}} |
|||
<pre> |
|||
2: 7.67405677335E444 |
|||
1: 4.96527238625E290 |
|||
</pre> |
|||
=={{header|Ruby}}== |
|||
Float calculation as Tcl. |
|||
<syntaxhighlight lang="ruby">include Math |
|||
class Integer |
|||
def permutation(k) |
|||
(self-k+1 .. self).inject( :*) |
|||
end |
|||
def combination(k) |
|||
self.permutation(k) / (1 .. k).inject( :*) |
|||
end |
|||
def big_permutation(k) |
|||
exp( lgamma_plus(self) - lgamma_plus(self -k)) |
|||
end |
|||
def big_combination(k) |
|||
exp( lgamma_plus(self) - lgamma_plus(self - k) - lgamma_plus(k)) |
|||
end |
|||
private |
|||
def lgamma_plus(n) |
|||
lgamma(n+1)[0] #lgamma is the natural log of gamma |
|||
end |
|||
end |
|||
p 12.permutation(9) #=> 79833600 |
|||
p 12.big_permutation(9) #=> 79833600.00000021 |
|||
p 60.combination(53) #=> 386206920 |
|||
p 145.big_permutation(133) #=> 1.6801459655817956e+243 |
|||
p 900.big_combination(450) #=> 2.247471882064647e+269 |
|||
p 1000.big_combination(969) #=> 7.602322407770517e+58 |
|||
p 15000.big_permutation(73) #=> 6.004137561717704e+304 |
|||
#That's about the maximum of Float: |
|||
p 15000.big_permutation(74) #=> Infinity |
|||
#Fixnum has no maximum: |
|||
p 15000.permutation(74) #=> 896237613852967826239917238565433149353074416025197784301593335243699358040738127950872384197159884905490054194835376498534786047382445592358843238688903318467070575184552953997615178973027752714539513893159815472948987921587671399790410958903188816684444202526779550201576117111844818124800000000000000000000 |
|||
</syntaxhighlight> |
|||
Ruby's Arrays have a permutation and a combination method which result in (lazy) enumerators. These Enumerators have a "size" method, which returns the size of the enumerator, or nil if it can’t be calculated lazily. (Since Ruby 2.0) |
|||
<syntaxhighlight lang="ruby">(1..60).to_a.combination(53).size #=> 386206920</syntaxhighlight> |
|||
=={{header|Rust}}== |
|||
{{trans|zig}} |
|||
Almost a verbatim port... the logic is retained but I renounce anyway to use `io::stdout()`, `println!()` is enough. I wonder why f64?! |
|||
<syntaxhighlight lang="rust"> |
|||
fn perm(n: f64, k: f64) -> f64 { |
|||
let mut result: f64 = 1.0; |
|||
let mut i: f64 = 0.0; |
|||
while i < k { |
|||
result *= n - i; |
|||
i += 1.0; |
|||
} |
|||
result |
|||
} |
|||
fn comb(n: f64, k: f64) -> f64 { |
|||
perm(n, k) / perm(k, k) |
|||
} |
|||
fn main() { |
|||
const P: f64 = 12.0; |
|||
const C: f64 = 60.0; |
|||
let mut j: f64 = 1.0; |
|||
let mut k: f64 = 10.0; |
|||
while j < P { |
|||
println!("P({},{}) = {}", P, j, perm(P, j).floor()); |
|||
j += 1.0; |
|||
} |
|||
while k < C { |
|||
println!("C({},{}) = {}", C, k, comb(C, k).floor()); |
|||
k += 10.0; |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
P(12,1) = 12 |
|||
P(12,2) = 132 |
|||
P(12,3) = 1320 |
|||
P(12,4) = 11880 |
|||
P(12,5) = 95040 |
|||
P(12,6) = 665280 |
|||
P(12,7) = 3991680 |
|||
P(12,8) = 19958400 |
|||
P(12,9) = 79833600 |
|||
P(12,10) = 239500800 |
|||
P(12,11) = 479001600 |
|||
C(60,10) = 75394027566 |
|||
C(60,20) = 4191844505805495 |
|||
C(60,30) = 118264581564861420 |
|||
C(60,40) = 4191844505805495 |
|||
C(60,50) = 75394027566 |
|||
</pre> |
|||
=={{header|Scheme}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
(define (combinations n k) |
|||
(do ((i 0 (+ 1 i)) |
|||
(res 1 (/ (* res (- n i)) |
|||
(- k i)))) |
|||
((= i k) res))) |
|||
(define (permutations n k) |
|||
(do ((i 0 (+ 1 i)) |
|||
(res 1 (* res (- n i)))) |
|||
((= i k) res))) |
|||
(display "P(4,2) = ") (display (permutations 4 2)) (newline) |
|||
(display "P(8,2) = ") (display (permutations 8 2)) (newline) |
|||
(display "P(10,8) = ") (display (permutations 10 8)) (newline) |
|||
(display "C(10,8) = ") (display (combinations 10 8)) (newline) |
|||
(display "C(20,8) = ") (display (combinations 20 8)) (newline) |
|||
(display "C(60,58) = ") (display (combinations 60 58)) (newline) |
|||
(display "P(1000,10) = ") (display (permutations 1000 10)) (newline) |
|||
(display "P(1000,20) = ") (display (permutations 1000 20)) (newline) |
|||
(display "P(15000,2) = ") (display (permutations 15000 3)) (newline) |
|||
(display "C(1000,10) = ") (display (combinations 1000 10)) (newline) |
|||
(display "C(1000,999) = ") (display (combinations 1000 999)) (newline) |
|||
(display "C(1000,1000) = ") (display (combinations 1000 1000)) (newline) |
|||
(display "C(15000,14998) = ") (display (combinations 15000 14998)) (newline) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
P(4,2) = 12 |
|||
P(8,2) = 56 |
|||
P(10,8) = 1814400 |
|||
C(10,8) = 45 |
|||
C(20,8) = 125970 |
|||
C(60,58) = 1770 |
|||
P(1000,10) = 955860613004397508326213120000 |
|||
P(1000,20) = 825928413359200443640727373872992573951185652339949568000000 |
|||
P(15000,2) = 3374325030000 |
|||
C(1000,10) = 263409560461970212832400 |
|||
C(1000,999) = 1000 |
|||
C(1000,1000) = 1 |
|||
C(15000,14998) = 112492500 |
|||
</pre> |
|||
=={{header|Sidef}}== |
|||
{{trans|Raku}} |
|||
<syntaxhighlight lang="ruby">func P(n, k) { n! / ((n-k)!) } |
|||
func C(n, k) { binomial(n, k) } |
|||
class Logarithm(value) { |
|||
method to_s { |
|||
var e = int(value/10.log) |
|||
"%.8fE%+d" % (exp(value - e*10.log), e) |
|||
} |
|||
} |
|||
func lstirling(n) { |
|||
n < 10 ? (lstirling(n+1) - log(n+1)) |
|||
: (0.5*log(2*Num.pi*n) + n*log(n/Num.e + 1/(12*Num.e*n))) |
|||
} |
|||
func P_approx(n, k) { |
|||
Logarithm((lstirling(n) - lstirling(n -k))) |
|||
} |
|||
func C_approx(n, k) { |
|||
Logarithm((lstirling(n) - lstirling(n -k) - lstirling(k))) |
|||
} |
|||
say "=> Exact results:" |
|||
for n (1..12) { |
|||
var p = n//3 |
|||
say "P(#{n}, #{p}) = #{P(n, p)}" |
|||
} |
|||
for n (10..60 `by` 10) { |
|||
var p = n//3 |
|||
say "C(#{n}, #{p}) = #{C(n, p)}" |
|||
} |
|||
say ''; |
|||
say "=> Floating point approximations:" |
|||
for n ([5, 50, 500, 1000, 5000, 15000]) { |
|||
var p = n//3 |
|||
say "P(#{n}, #{p}) = #{P_approx(n, p)}" |
|||
} |
|||
for n (100..1000 `by` 100) { |
|||
var p = n//3 |
|||
say "C(#{n}, #{p}) = #{C_approx(n, p)}" |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
=> Exact results: |
|||
P(1, 0) = 1 |
|||
P(2, 0) = 1 |
|||
P(3, 1) = 3 |
|||
P(4, 1) = 4 |
|||
P(5, 1) = 5 |
|||
P(6, 2) = 30 |
|||
P(7, 2) = 42 |
|||
P(8, 2) = 56 |
|||
P(9, 3) = 504 |
|||
P(10, 3) = 720 |
|||
P(11, 3) = 990 |
|||
P(12, 4) = 11880 |
|||
C(10, 3) = 120 |
|||
C(20, 6) = 38760 |
|||
C(30, 10) = 30045015 |
|||
C(40, 13) = 12033222880 |
|||
C(50, 16) = 4923689695575 |
|||
C(60, 20) = 4191844505805495 |
|||
=> Floating point approximations: |
|||
P(5, 1) = 5.00000000E+0 |
|||
P(50, 16) = 1.03017326E+26 |
|||
P(500, 166) = 3.53487492E+434 |
|||
P(1000, 333) = 5.96932629E+971 |
|||
P(5000, 1666) = 6.85674576E+6025 |
|||
P(15000, 5000) = 9.64985399E+20469 |
|||
C(100, 33) = 2.94692433E+26 |
|||
C(200, 66) = 7.26975256E+53 |
|||
C(300, 100) = 4.15825147E+81 |
|||
C(400, 133) = 1.25794868E+109 |
|||
C(500, 166) = 3.92602839E+136 |
|||
C(600, 200) = 2.50601778E+164 |
|||
C(700, 233) = 8.10320356E+191 |
|||
C(800, 266) = 2.64562336E+219 |
|||
C(900, 300) = 1.74335637E+247 |
|||
C(1000, 333) = 5.77613455E+274 |
|||
</pre> |
|||
=={{header|Stata}}== |
|||
The '''[https://www.stata.com/help.cgi?mf_comb comb]''' function is builtin. Here is an implementation, together with perm: |
|||
<syntaxhighlight lang="stata">real scalar comb1(n, k) { |
|||
return(exp(lnfactorial(n)-lnfactorial(k)-lnfactorial(n-k))) |
|||
} |
|||
real scalar perm(n, k) { |
|||
return(exp(lnfactorial(n)-lnfactorial(n-k))) |
|||
}</syntaxhighlight> |
|||
=={{header|Swift}}== |
|||
{{trans|Kotlin}} |
|||
Using AttaSwift's BigInt |
|||
<syntaxhighlight lang="swift">import BigInt |
|||
func permutations(n: Int, k: Int) -> BigInt { |
|||
let l = n - k + 1 |
|||
guard l <= n else { |
|||
return 1 |
|||
} |
|||
return (l...n).reduce(BigInt(1), { $0 * BigInt($1) }) |
|||
} |
|||
func combinations(n: Int, k: Int) -> BigInt { |
|||
let fact = {() -> BigInt in |
|||
guard k > 1 else { |
|||
return 1 |
|||
} |
|||
return (2...k).map({ BigInt($0) }).reduce(1, *) |
|||
}() |
|||
return permutations(n: n, k: k) / fact |
|||
} |
|||
print("Sample of permutations from 1 to 12") |
|||
for i in 1...12 { |
|||
print("\(i) P \(i / 3) = \(permutations(n: i, k: i / 3))") |
|||
} |
|||
print("\nSample of combinations from 10 to 60") |
|||
for i in stride(from: 10, through: 60, by: 10) { |
|||
print("\(i) C \(i / 3) = \(combinations(n: i, k: i / 3))") |
|||
} |
|||
print("\nSample of permutations from 5 to 15,000") |
|||
for i in [5, 50, 500, 1000, 5000, 15000] { |
|||
let k = i / 3 |
|||
let res = permutations(n: i, k: k).description |
|||
let extra = res.count > 40 ? "... (\(res.count - 40) more digits)" : "" |
|||
print("\(i) P \(k) = \(res.prefix(40))\(extra)") |
|||
} |
|||
print("\nSample of combinations from 100 to 1000") |
|||
for i in stride(from: 100, through: 1000, by: 100) { |
|||
let k = i / 3 |
|||
let res = combinations(n: i, k: k).description |
|||
let extra = res.count > 40 ? "... (\(res.count - 40) more digits)" : "" |
|||
print("\(i) C \(k) = \(res.prefix(40))\(extra)") |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Sample of permutations from 1 to 12 |
|||
1 P 0 = 1 |
|||
2 P 0 = 1 |
|||
3 P 1 = 3 |
|||
4 P 1 = 4 |
|||
5 P 1 = 5 |
|||
6 P 2 = 30 |
|||
7 P 2 = 42 |
|||
8 P 2 = 56 |
|||
9 P 3 = 504 |
|||
10 P 3 = 720 |
|||
11 P 3 = 990 |
|||
12 P 4 = 11880 |
|||
Sample of combinations from 10 to 60 |
|||
10 C 3 = 120 |
|||
20 C 6 = 38760 |
|||
30 C 10 = 30045015 |
|||
40 C 13 = 12033222880 |
|||
50 C 16 = 4923689695575 |
|||
60 C 20 = 4191844505805495 |
|||
Sample of permutations from 5 to 15,000 |
|||
5 P 1 = 5 |
|||
50 P 16 = 103017324974226408345600000 |
|||
500 P 166 = 3534874921742942787609361826601762306844... (395 more digits) |
|||
1000 P 333 = 5969326288503415089039701765900784280998... (932 more digits) |
|||
5000 P 1666 = 6856745757255674275484536940248896062234... (5986 more digits) |
|||
15000 P 5000 = 9649853988727493922014858805931295980792... (20430 more digits) |
|||
Sample of combinations from 100 to 1000 |
|||
100 C 33 = 294692427022540894366527900 |
|||
200 C 66 = 7269752545169278341527066651192738976755... (14 more digits) |
|||
300 C 100 = 4158251463258564744783383526326405580280... (42 more digits) |
|||
400 C 133 = 1257948684182108702133348475651965004491... (70 more digits) |
|||
500 C 166 = 3926028386194422755220408345072331428197... (97 more digits) |
|||
600 C 200 = 2506017783221402805005616770513228835202... (125 more digits) |
|||
700 C 233 = 8103203563339599904740453644031138232944... (152 more digits) |
|||
800 C 266 = 2645623362683627034288829299556124255091... (180 more digits) |
|||
900 C 300 = 1743356373296446642960730765085718347630... (208 more digits) |
|||
1000 C 333 = 5776134553147651669777486323549601722339... (235 more digits)</pre> |
|||
=={{header|Tcl}}== |
|||
Tcl doesn't allow the definition of new infix operators, so we define <math>P</math> and <math>C</math> as ordinary functions. There are no problems with loss of significance though: Tcl has supported arbitrary precision integer arithmetic since 8.5. |
|||
{{tcllib|math}} |
|||
<syntaxhighlight lang="tcl"># Exact integer versions |
|||
proc tcl::mathfunc::P {n k} { |
|||
set t 1 |
|||
for {set i $n} {$i > $n-$k} {incr i -1} { |
|||
set t [expr {$t * $i}] |
|||
} |
|||
return $t |
|||
} |
|||
proc tcl::mathfunc::C {n k} { |
|||
set t [P $n $k] |
|||
for {set i $k} {$i > 1} {incr i -1} { |
|||
set t [expr {$t / $i}] |
|||
} |
|||
return $t |
|||
} |
|||
# Floating point versions using the Gamma function |
|||
package require math |
|||
proc tcl::mathfunc::lnGamma n {math::ln_Gamma $n} |
|||
proc tcl::mathfunc::fP {n k} { |
|||
expr {exp(lnGamma($n+1) - lnGamma($n-$k+1))} |
|||
} |
|||
proc tcl::mathfunc::fC {n k} { |
|||
expr {exp(lnGamma($n+1) - lnGamma($n-$k+1) - lnGamma($k+1))} |
|||
}</syntaxhighlight> |
|||
Demonstrating: |
|||
<syntaxhighlight lang="tcl"># Using the exact integer versions |
|||
puts "A sample of Permutations from 1 to 12:" |
|||
for {set i 4} {$i <= 12} {incr i} { |
|||
set ii [expr {$i - 2}] |
|||
set iii [expr {$i - int(sqrt($i))}] |
|||
puts "$i P $ii = [expr {P($i,$ii)}], $i P $iii = [expr {P($i,$iii)}]" |
|||
} |
|||
puts "A sample of Combinations from 10 to 60:" |
|||
for {set i 10} {$i <= 60} {incr i 10} { |
|||
set ii [expr {$i - 2}] |
|||
set iii [expr {$i - int(sqrt($i))}] |
|||
puts "$i C $ii = [expr {C($i,$ii)}], $i C $iii = [expr {C($i,$iii)}]" |
|||
} |
|||
# Using the approximate floating point versions |
|||
puts "A sample of Permutations from 5 to 15000:" |
|||
for {set i 5} {$i <= 150} {incr i 10} { |
|||
set ii [expr {$i - 2}] |
|||
set iii [expr {$i - int(sqrt($i))}] |
|||
puts "$i P $ii = [expr {fP($i,$ii)}], $i P $iii = [expr {fP($i,$iii)}]" |
|||
} |
|||
puts "A sample of Combinations from 100 to 1000:" |
|||
for {set i 100} {$i <= 1000} {incr i 100} { |
|||
set ii [expr {$i - 2}] |
|||
set iii [expr {$i - int(sqrt($i))}] |
|||
puts "$i C $ii = [expr {fC($i,$ii)}], $i C $iii = [expr {fC($i,$iii)}]" |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A sample of Permutations from 1 to 12: |
|||
4 P 2 = 12, 4 P 2 = 12 |
|||
5 P 3 = 60, 5 P 3 = 60 |
|||
6 P 4 = 360, 6 P 4 = 360 |
|||
7 P 5 = 2520, 7 P 5 = 2520 |
|||
8 P 6 = 20160, 8 P 6 = 20160 |
|||
9 P 7 = 181440, 9 P 6 = 60480 |
|||
10 P 8 = 1814400, 10 P 7 = 604800 |
|||
11 P 9 = 19958400, 11 P 8 = 6652800 |
|||
12 P 10 = 239500800, 12 P 9 = 79833600 |
|||
A sample of Combinations from 10 to 60: |
|||
10 C 8 = 45, 10 C 7 = 120 |
|||
20 C 18 = 190, 20 C 16 = 4845 |
|||
30 C 28 = 435, 30 C 25 = 142506 |
|||
40 C 38 = 780, 40 C 34 = 3838380 |
|||
50 C 48 = 1225, 50 C 43 = 99884400 |
|||
60 C 58 = 1770, 60 C 53 = 386206920 |
|||
A sample of Permutations from 5 to 15000: |
|||
5 P 3 = 59.9999999964319, 5 P 3 = 59.9999999964319 |
|||
15 P 13 = 653837183936.7548, 15 P 12 = 217945727984.54794 |
|||
25 P 23 = 7.755605021026223e+24, 25 P 20 = 1.2926008369145724e+23 |
|||
35 P 33 = 5.166573982873315e+39, 35 P 30 = 8.610956638634269e+37 |
|||
45 P 43 = 5.981111043018166e+55, 45 P 39 = 1.6614197342883882e+53 |
|||
55 P 53 = 6.348201676661335e+72, 55 P 48 = 2.5191276496660396e+69 |
|||
65 P 63 = 4.123825295988996e+90, 65 P 57 = 2.0455482620718488e+86 |
|||
75 P 73 = 1.2404570405684596e+109, 75 P 67 = 6.153060717624475e+104 |
|||
85 P 83 = 1.4085520572027225e+128, 85 P 76 = 7.763183737477006e+122 |
|||
95 P 93 = 5.164989244208789e+147, 95 P 86 = 2.846665148075141e+142 |
|||
105 P 103 = 5.406983791334563e+167, 105 P 95 = 2.980039567808848e+161 |
|||
115 P 113 = 1.462546846791721e+188, 115 P 105 = 8.060774068156828e+181 |
|||
125 P 123 = 9.413385884788385e+208, 125 P 114 = 4.716503269639238e+201 |
|||
135 P 133 = 1.345236353714729e+230, 135 P 124 = 6.74020138809567e+222 |
|||
145 P 143 = 4.0239630289197437e+251, 145 P 133 = 1.6801459658196038e+243 |
|||
A sample of Combinations from 100 to 1000: |
A sample of Combinations from 100 to 1000: |
||
100 C 98 = 4950.000000564707, 100 C 90 = 17310309460118.861 |
|||
200 C 198 = 19900.000002250566, 200 C 186 = 1.1797916416885855e+21 |
|||
300 C 298 = 44850.00000506082, 300 C 283 = 2.287708142503998e+27 |
|||
400 C 398 = 79800.00000901309, 400 C 380 = 2.788360984244711e+33 |
|||
500 C 498 = 124750.00001405331, 500 C 478 = 1.327364247175741e+38 |
|||
600 C 598 = 179700.00002031153, 600 C 576 = 4.7916866834178515e+42 |
|||
700 C 698 = 244650.00002750417, 700 C 674 = 1.454786513417567e+47 |
|||
800 C 798 = 319600.0000360682, 800 C 772 = 3.933526871778561e+51 |
|||
900 C 898 = 404550.0000452471, 900 C 870 = 9.803348169192494e+55 |
|||
1000 C 998 = 499500.0000564987, 1000 C 969 = 7.602322409167201e+58 |
|||
</pre> |
|||
It should be noted that for large values, it can be ''much'' faster to use the floating point version (at a cost of losing significance). In particular <code>expr C(1000,500)</code> takes approximately 1000 times longer to compute than <code>expr fC(1000,500)</code> |
|||
=={{header|VBScript}}== |
|||
<syntaxhighlight lang="vb">' Combinations and permutations - vbs - 10/04/2017 |
|||
dim i,j |
|||
Wscript.StdOut.WriteLine "-- Long Integer - Permutations - from 1 to 12" |
|||
for i=1 to 12 |
|||
for j=1 to i |
|||
Wscript.StdOut.Write "P(" & i & "," & j & ")=" & perm(i,j) & " " |
|||
next 'j |
|||
Wscript.StdOut.WriteLine "" |
|||
next 'i |
|||
Wscript.StdOut.WriteLine "-- Float integer - Combinations from 10 to 60" |
|||
for i=10 to 60 step 10 |
|||
for j=1 to i step i\5 |
|||
Wscript.StdOut.Write "C(" & i & "," & j & ")=" & comb(i,j) & " " |
|||
next 'j |
|||
Wscript.StdOut.WriteLine "" |
|||
next 'i |
|||
Wscript.StdOut.WriteLine "-- Float integer - Permutations from 5000 to 15000" |
|||
for i=5000 to 15000 step 5000 |
|||
for j=10 to 70 step 20 |
|||
Wscript.StdOut.Write "C(" & i & "," & j & ")=" & perm(i,j) & " " |
|||
next 'j |
|||
Wscript.StdOut.WriteLine "" |
|||
next 'i |
|||
Wscript.StdOut.WriteLine "-- Float integer - Combinations from 200 to 1000" |
|||
for i=200 to 1000 step 200 |
|||
for j=20 to 100 step 20 |
|||
Wscript.StdOut.Write "P(" & i & "," & j & ")=" & comb(i,j) & " " |
|||
next 'j |
|||
Wscript.StdOut.WriteLine "" |
|||
next 'i |
|||
function perm(x,y) |
|||
dim i,z |
|||
z=1 |
|||
for i=x-y+1 to x |
|||
z=z*i |
|||
next 'i |
|||
perm=z |
|||
end function 'perm |
|||
function fact(x) |
|||
dim i,z |
|||
z=1 |
|||
for i=2 to x |
|||
z=z*i |
|||
next 'i |
|||
fact=z |
|||
end function 'fact |
|||
function comb(byval x,byval y) |
|||
if y>x then |
|||
comb=0 |
|||
elseif x=y then |
|||
comb=1 |
|||
else |
|||
if x-y<y then y=x-y |
|||
comb=perm(x,y)/fact(y) |
|||
end if |
|||
end function 'comb</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:40ex"> |
|||
-- Long Integer - Permutations - from 1 to 12 |
|||
P(1,1)=1 |
|||
P(2,1)=2 P(2,2)=2 |
|||
P(3,1)=3 P(3,2)=6 P(3,3)=6 |
|||
P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 |
|||
P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 |
|||
P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 |
|||
P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 |
|||
P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 |
|||
P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 |
|||
P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 |
|||
P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 |
|||
P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 |
|||
-- Float integer - Combinations from 10 to 60 |
|||
C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 |
|||
C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 |
|||
C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 |
|||
C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 |
|||
C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 |
|||
C(60,1)=60 C(60,13)=5166863427600 C(60,25)=5,19154379743283E+16 C(60,37)=2,33853324208686E+16 C(60,49)=342700125300 |
|||
-- Float integer - Permutations from 5000 to 15000 |
|||
C(5000,10)=9,67807348145655E+36 C(5000,30)=8,53575581200676E+110 C(5000,50)=6,94616656703754E+184 C(5000,70)=5,21383580146194E+258 |
|||
C(10000,10)=9,95508690556325E+39 C(10000,30)=9,57391540294832E+119 C(10000,50)=8,84526658067387E+199 C(10000,70)=7,850079552152E+279 |
|||
C(15000,10)=5,74922667554068E+41 C(15000,30)=1,86266591363916E+125 C(15000,50)=5,87565776023335E+208 C(15000,70)=1,80450662858719E+292 |
|||
-- Float integer - Combinations from 200 to 1000 |
|||
P(200,20)=1,61358778796735E+27 P(200,40)=2,05015799519859E+42 P(200,60)=7,04050484926892E+51 P(200,80)=1,64727865245176E+57 P(200,100)=9,05485146561033E+58 |
|||
P(400,20)=2,7883609836709E+33 P(400,40)=1,9703374084393E+55 P(400,60)=1,50867447857277E+72 P(400,80)=4,22814216193593E+85 P(400,100)=2,24185479155434E+96 |
|||
P(600,20)=1,09108668819553E+37 P(600,40)=4,33518929550349E+62 P(600,60)=2,77426667704894E+83 P(600,80)=1,00412999166192E+101 P(600,100)=1,11141121906619E+116 |
|||
P(800,20)=3,72976760205571E+39 P(800,40)=6,04464684067502E+67 P(800,60)=1,90370080982158E+91 P(800,80)=4,14170924105943E+111 P(800,100)=3,4111376846871E+129 |
|||
P(1000,20)=3,39482811302458E+41 P(1000,40)=5,55974423571664E+71 P(1000,60)=1,97427486218598E+97 P(1000,80)=5,43269728730706E+119 P(1000,100)=6,38505119263051E+139 |
|||
</pre> |
|||
=={{header|Visual Basic .NET}}== |
|||
{{works with|Visual Basic .NET|2013}} |
|||
<syntaxhighlight lang="vbnet">' Combinations and permutations - 10/04/2017 |
|||
Imports System.Numerics 'BigInteger |
|||
Module CombPermRc |
|||
Sub Main() |
|||
Dim i, j As Long |
|||
For i = 1 To 12 |
|||
For j = 1 To i |
|||
Console.Write("P(" & i & "," & j & ")=" & PermBig(i, j).ToString & " ") |
|||
Next j |
|||
Console.WriteLine("") |
|||
Next i |
|||
Console.WriteLine("--") |
|||
For i = 10 To 60 Step 10 |
|||
For j = 1 To i Step i \ 5 |
|||
Console.Write("C(" & i & "," & j & ")=" & CombBig(i, j).ToString & " ") |
|||
Next j |
|||
Console.WriteLine("") |
|||
Next i |
|||
Console.WriteLine("--") |
|||
For i = 5000 To 15000 Step 5000 |
|||
For j = 4000 To 5000 Step 1000 |
|||
Console.Write("P(" & i & "," & j & ")=" & PermBig(i, j).ToString("E") & " ") |
|||
Next j |
|||
Console.WriteLine("") |
|||
Next i |
|||
Console.WriteLine("--") |
|||
For i = 5000 To 15000 Step 5000 |
|||
For j = 4000 To 5000 Step 1000 |
|||
Console.Write("C(" & i & "," & j & ")=" & CombBig(i, j).ToString("E") & " ") |
|||
Next j |
|||
Console.WriteLine("") |
|||
Next i |
|||
Console.WriteLine("--") |
|||
i = 5000 : j = 4000 |
|||
Console.WriteLine("C(" & i & "," & j & ")=" & CombBig(i, j).ToString) |
|||
End Sub 'Main |
|||
Function PermBig(x As Long, y As Long) As BigInteger |
|||
Dim i As Long, z As BigInteger |
|||
z = 1 |
|||
For i = x - y + 1 To x |
|||
z = z * i |
|||
Next i |
|||
Return (z) |
|||
End Function 'PermBig |
|||
Function FactBig(x As Long) As BigInteger |
|||
Dim i As Long, z As BigInteger |
|||
z = 1 |
|||
For i = 2 To x |
|||
z = z * i |
|||
Next i |
|||
Return (z) |
|||
End Function 'FactBig |
|||
Function CombBig(ByVal x As Long, ByVal y As Long) As BigInteger |
|||
If y > x Then |
|||
Return (0) |
|||
ElseIf x = y Then |
|||
Return (1) |
|||
Else |
|||
If x - y < y Then y = x - y |
|||
Return (PermBig(x, y) / FactBig(y)) |
|||
End If |
|||
End Function 'CombBig |
|||
End Module</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:40ex"> |
|||
P(1,1)=1 |
|||
P(2,1)=2 P(2,2)=2 |
|||
P(3,1)=3 P(3,2)=6 P(3,3)=6 |
|||
P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 |
|||
P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 |
|||
P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 |
|||
P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 |
|||
P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 |
|||
P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 |
|||
P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 |
|||
P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 |
|||
P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 |
|||
-- |
|||
C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 |
|||
C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 |
|||
C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 |
|||
C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 |
|||
C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 |
|||
C(60,1)=60 C(60,13)=5166863427600 C(60,25)=51915437974328292 C(60,37)=23385332420868600 C(60,49)=342700125300 |
|||
-- |
|||
P(5000,4000)=1,050873E+13758 P(5000,5000)=4,228578E+16325 |
|||
P(10000,4000)=1,060455E+15594 P(10000,5000)=6,731009E+19333 |
|||
P(15000,4000)=8,685001E+16448 P(15000,5000)=9,649854E+20469 |
|||
-- |
|||
C(5000,4000)=5,746236E+1084 C(5000,5000)=1,000000E+000 |
|||
C(10000,4000)=5,798630E+2920 C(10000,5000)=1,591790E+3008 |
|||
C(15000,4000)=4,749011E+3775 C(15000,5000)=2,282057E+4144 |
|||
-- |
|||
C(5000,4000)=57462357505803375604893834658665168251899919793850512934468881710397678593302188064618445132583370701755893065787216750992391223467601994741594656878559929037277303674963658032197224327768110236651567704673226756781828332650887849150208195780031161286578505113618731045004523840401144118298192191997565735245181433457469532981432785237769191864102953974244072964471109551273603780184330987071947790993108191904370472373403157802158903129815170101708451875442019845175637901995588390614304812103202403626211504997668649346891167495657556154392183988627948442807346603688457854135114491955258804187129028256547543888109987151649038111791932035229202856007767332717845596528598314477979861265222941138323298702349967224867703420888363395662988291273283611081068577160905840445308086112429900453394212790633910614322699210850302387512579976209123523546689147207974269396548873838155355768985614160932799226261509866933143702889005270480654844312094564956178277998090168826124850606847021667494019587077659107276117413835912767949017954979839258481340540145909025953956582025656306426226560 |
|||
</pre> |
|||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
{{libheader|Wren-big}} |
|||
{{libheader|Wren-fmt}} |
|||
{{libheader|Wren-iterate}} |
|||
<syntaxhighlight lang="wren">import "./big" for BigInt |
|||
import "./fmt" for Fmt |
|||
import "./iterate" for Stepped |
|||
var perm = Fn.new { |n, k| |
|||
if (n <= 0 || k < 0) Fiber.abort("Invalid argument(s).") |
|||
if (k == 0) return BigInt.one |
|||
return (n-k+1..n).reduce(BigInt.one) { |acc, i| acc * BigInt.new(i) } |
|||
} |
|||
var comb = Fn.new { |n, k| |
|||
if (n <= 0 || k < 0) Fiber.abort("Invalid argument(s).") |
|||
var fact = BigInt.one |
|||
if (k > 1) fact = (2..k).reduce(BigInt.one) { |acc, i| acc * BigInt.new(i) } |
|||
return perm.call(n, k) / fact |
|||
} |
|||
System.print("A sample of permutations from 1 to 12:") |
|||
for (n in 1..12) Fmt.print("$2d P $-2d = $i", n, (n/3).floor, perm.call(n, (n/3).floor)) |
|||
System.print("\nA sample of combinations from 10 to 60:") |
|||
for (n in Stepped.new(10..60, 10)) { |
|||
Fmt.print("$2d C $-2d = $i", n, (n/3).floor, comb.call(n, (n/3).floor)) |
|||
} |
|||
System.print("\nA sample of permutations from 5 to 15000:") |
|||
var na = [5, 50, 500, 1000, 5000, 15000] |
|||
for (n in na) { |
|||
var k = (n/3).floor |
|||
var s = perm.call(n, k).toString |
|||
var l = s.count |
|||
var e = (l <= 40) ? "" : "... (%(l - 40) more digits)" |
|||
Fmt.print("$5d P $-4d = $s$s", n, k, s.take(40).join(), e) |
|||
} |
|||
System.print("\nA sample of combinations from 100 to 1000:") |
|||
for (n in Stepped.new(100..1000, 100)) { |
|||
var k = (n/3).floor |
|||
var s = comb.call(n, k).toString |
|||
var l = s.count |
|||
var e = (l <= 40) ? "" : "... (%(l - 40) more digits)" |
|||
Fmt.print("$4d C $-3d = $s$s", n, k, s.take(40).join(), e) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
A sample of permutations from 1 to 12: |
|||
1 P 0 = 1 |
|||
2 P 0 = 1 |
|||
3 P 1 = 3 |
|||
4 P 1 = 4 |
|||
5 P 1 = 5 |
|||
6 P 2 = 30 |
|||
7 P 2 = 42 |
|||
8 P 2 = 56 |
|||
9 P 3 = 504 |
|||
10 P 3 = 720 |
|||
11 P 3 = 990 |
|||
12 P 4 = 11880 |
|||
A sample of combinations from 10 to 60: |
|||
10 C 3 = 120 |
|||
20 C 6 = 38760 |
|||
30 C 10 = 30045015 |
|||
40 C 13 = 12033222880 |
|||
50 C 16 = 4923689695575 |
|||
60 C 20 = 4191844505805495 |
|||
A sample of permutations from 5 to 15000: |
|||
5 P 1 = 5 |
|||
50 P 16 = 103017324974226408345600000 |
|||
500 P 166 = 3534874921742942787609361826601762306844... (395 more digits) |
|||
1000 P 333 = 5969326288503415089039701765900784280998... (932 more digits) |
|||
5000 P 1666 = 6856745757255674275484536940248896062234... (5986 more digits) |
|||
15000 P 5000 = 9649853988727493922014858805931295980792... (20430 more digits) |
|||
A sample of combinations from 100 to 1000: |
|||
100 C 33 = 294692427022540894366527900 |
|||
200 C 66 = 7269752545169278341527066651192738976755... (14 more digits) |
|||
300 C 100 = 4158251463258564744783383526326405580280... (42 more digits) |
|||
400 C 133 = 1257948684182108702133348475651965004491... (70 more digits) |
|||
500 C 166 = 3926028386194422755220408345072331428197... (97 more digits) |
|||
600 C 200 = 2506017783221402805005616770513228835202... (125 more digits) |
|||
700 C 233 = 8103203563339599904740453644031138232944... (152 more digits) |
|||
800 C 266 = 2645623362683627034288829299556124255091... (180 more digits) |
|||
900 C 300 = 1743356373296446642960730765085718347630... (208 more digits) |
|||
1000 C 333 = 5776134553147651669777486323549601722339... (235 more digits) |
|||
</pre> |
|||
=={{header|zig}}== |
|||
<syntaxhighlight lang="zig> const std = @import("std"); |
|||
const num = f64; |
|||
pub fn perm(n: num, k: num) num { |
|||
var result: num = 1; |
|||
var i: num = 0; |
|||
while (i < k) : (i += 1) { |
|||
result *= n - i; |
|||
} |
|||
return result; |
|||
} |
|||
pub fn comb(n: num, k: num) num { |
|||
return perm(n, k) / perm(k, k); |
|||
} |
|||
pub fn main() !void { |
|||
var stdout = std.io.getStdOut().writer(); |
|||
const p: num = 12; |
|||
const c: num = 60; |
|||
var j: num = 1; |
|||
var k: num = 10; |
|||
while (j < p) : (j += 1) { |
|||
try stdout.print("P({d},{d}) = {d}\n", .{ p, j, @floor(perm(p, j)) }); |
|||
} |
|||
while (k < c) : (k += 10) { |
|||
try stdout.print("C({d},{d}) = {d}\n", .{ c, k, @floor(comb(c, k)) }); |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
P(12,1) = 12 |
|||
P(12,2) = 132 |
|||
P(12,3) = 1320 |
|||
P(12,4) = 11880 |
|||
P(12,5) = 95040 |
|||
P(12,6) = 665280 |
|||
P(12,7) = 3991680 |
|||
P(12,8) = 19958400 |
|||
P(12,9) = 79833600 |
|||
P(12,10) = 239500800 |
|||
P(12,11) = 479001600 |
|||
C(60,10) = 75394027566 |
|||
C(60,20) = 4191844505805495 |
|||
C(60,30) = 118264581564861420 |
|||
C(60,40) = 4191844505805495 |
|||
C(60,50) = 75394027566 |
|||
</pre> |
</pre> |
Latest revision as of 11:58, 8 February 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
This page uses content from Wikipedia. The original article was at Combination. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
This page uses content from Wikipedia. The original article was at Permutation. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
- Task
Implement the combination (nCk) and permutation (nPk) operators in the target language:
See the Wikipedia articles for a more detailed description.
To test, generate and print examples of:
- A sample of permutations from 1 to 12 and Combinations from 10 to 60 using exact Integer arithmetic.
- A sample of permutations from 5 to 15000 and Combinations from 100 to 1000 using approximate Floating point arithmetic.
This 'floating point' code could be implemented using an approximation, e.g., by calling the Gamma function.
- Related task
The number of samples of size k from n objects.
With combinations and permutations generation tasks.
Order Unimportant Order Important Without replacement Task: Combinations Task: Permutations With replacement Task: Combinations with repetitions Task: Permutations with repetitions
11l
F perm(=n, p)
BigInt r = 1
V k = n - p
L n > k
r *= n--
R r
F comb(n, =k)
V r = perm(n, k)
L k > 0
r I/= k--
R r
L(i) 1..11
print(‘P(12,’i‘) = ’perm(12, i))
L(i) (10.<60).step(10)
print(‘C(60,’i‘) = ’comb(60, i))
- Output:
P(12,1) = 12 P(12,2) = 132 P(12,3) = 1320 P(12,4) = 11880 P(12,5) = 95040 P(12,6) = 665280 P(12,7) = 3991680 P(12,8) = 19958400 P(12,9) = 79833600 P(12,10) = 239500800 P(12,11) = 479001600 C(60,10) = 75394027566 C(60,20) = 4191844505805495 C(60,30) = 118264581564861424 C(60,40) = 4191844505805495 C(60,50) = 75394027566
ALGOL 68
File: prelude_combinations_and_permutations.a68
# -*- coding: utf-8 -*- #
COMMENT REQUIRED by "prelude_combinations_and_permutations.a68" CO
MODE CPINT = #LONG# ~;
MODE CPOUT = #LONG# ~; # the answer, can be REAL #
MODE CPREAL = ~; # the answer, can be REAL #
PROC cp fix value error = (#REF# CPARGS args)BOOL: ~;
#PROVIDES:#
# OP C = (CP~,CP~)CP~: ~ #
# OP P = (CP~,CP~)CP~: ~ #
END COMMENT
MODE CPARGS = STRUCT(CHAR name, #REF# CPINT n,k);
PRIO C = 8, P = 8; # should be 7.5, a priority between *,/ and **,SHL,SHR etc #
# I suspect there is a more reliable way of doing this using the Gamma Function approx #
OP P = (CPINT n, r)CPOUT: (
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("P",n,r)) THEN stop FI FI;
CPOUT out := 1;
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r)! #
FOR i FROM n-r+1 TO n DO out *:= i OD;
out
);
OP P = (CPREAL n, r)CPREAL: # 'ln gamma' requires GSL library #
exp(ln gamma(n+1)-ln gamma(n-r+1));
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r)! #
COMMENT # alternate slower version #
OP P = (CPREAL n, r)CPREAL: ( # alternate slower version #
IF n < r ORF r < 0 THEN IF NOT cp fix value error(CPARGS("P",ENTIER n,ENTIER r)) THEN stop FI FI;
CPREAL out := 1;
# basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r)! #
CPREAL i := n-r+1;
WHILE i <= n DO
out*:= i;
# a crude check for underflow #
IF i = i + 1 THEN IF NOT cp fix value error(CPARGS("P",ENTIER n,ENTIER r)) THEN stop FI FI;
i+:=1
OD;
out
);
END COMMENT
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! #
OP C = (CPINT n, r)CPOUT: (
IF n < r ORF r < 0 THEN IF NOT cp fix value error(("C",n,r)) THEN stop FI FI;
CPINT largest = ( r > n - r | r | n - r );
CPINT smallest = n - largest;
CPOUT out := 1;
INT smaller fact := 2;
FOR larger fact FROM largest+1 TO n DO
# try and prevent overflow, p.s. there must be a smarter way to do this #
# Problems: loop stalls when 'smaller fact' is a largeish co prime #
out *:= larger fact;
WHILE smaller fact <= smallest ANDF out MOD smaller fact = 0 DO
out OVERAB smaller fact;
smaller fact +:= 1
OD
OD;
out # EXIT with: n P r OVER r P r #
);
OP C = (CPREAL n, CPREAL r)CPREAL: # 'ln gamma' requires GSL library #
exp(ln gamma(n+1)-ln gamma(n-r+1)-ln gamma(r+1));
# basically C(n,r) = nCk = nPk/r! = n!/(n-r)!/r! #
COMMENT # alternate slower version #
OP C = (CPREAL n, REAL r)CPREAL: (
IF n < r ORF r < 0 THEN IF NOT cp fix value error(("C",ENTIER n,ENTIER r)) THEN stop FI FI;
CPREAL largest = ( r > n - r | r | n - r );
CPREAL smallest = n - largest;
CPREAL out := 1;
REAL smaller fact := 2;
REAL larger fact := largest+1;
WHILE larger fact <= n DO # todo: check underflow here #
# try and prevent overflow, p.s. there must be a smarter way to do this #
out *:= larger fact;
WHILE smaller fact <= smallest ANDF out > smaller fact DO
out /:= smaller fact;
smaller fact +:= 1
OD;
larger fact +:= 1
OD;
out # EXIT with: n P r OVER r P r #
);
END COMMENT
SKIP
File: test_combinations_and_permutations.a68
#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #
CO REQUIRED by "prelude_combinations_and_permutations.a68" CO
MODE CPINT = #LONG# INT;
MODE CPOUT = #LONG# INT; # the answer, can be REAL #
MODE CPREAL = REAL; # the answer, can be REAL #
PROC cp fix value error = (#REF# CPARGS args)BOOL: (
putf(stand error, ($"Value error: "g(0)gg(0)"arg out of range"l$,
n OF args, name OF args, k OF args));
FALSE # unfixable #
);
#PROVIDES:#
# OP C = (CP~,CP~)CP~: ~ #
# OP P = (CP~,CP~)CP~: ~ #
PR READ "prelude_combinations_and_permutations.a68" PR;
printf($"A sample of Permutations from 1 to 12:"l$);
FOR i FROM 4 BY 1 TO 12 DO
INT first = i - 2,
second = i - ENTIER sqrt(i);
printf(($g(0)" P "g(0)" = "g(0)$, i, first, i P first, $", "$));
printf(($g(0)" P "g(0)" = "g(0)$, i, second, i P second, $l$))
OD;
printf($l"A sample of Combinations from 10 to 60:"l$);
FOR i FROM 10 BY 10 TO 60 DO
INT first = i - 2,
second = i - ENTIER sqrt(i);
printf(($"("g(0)" C "g(0)") = "g(0)$, i, first, i C first, $", "$));
printf(($"("g(0)" C "g(0)") = "g(0)$, i, second, i C second, $l$))
OD;
printf($l"A sample of Permutations from 5 to 15000:"l$);
FOR i FROM 5 BY 10 TO 150 DO
REAL r = i,
first = r - 2,
second = r - ENTIER sqrt(r);
printf(($g(0)" P "g(0)" = "g(-real width,real width-5,-1)$, r, first, r P first, $", "$));
printf(($g(0)" P "g(0)" = "g(-real width,real width-5,-1)$, r, second, r P second, $l$))
OD;
printf($l"A sample of Combinations from 10 to 190:"l$);
FOR i FROM 100 BY 100 TO 1000 DO
REAL r = i,
first = r - 2,
second = r - ENTIER sqrt(r);
printf(($"("g(0)" C "g(0)") = "g(0,1)$, r, first, r C first, $", "$));
printf(($"("g(0)" C "g(0)") = "g(0,1)$, r, second, r C second, $l$))
OD
Output:
A sample of Permutations from 1 to 12: 4 P 2 = 12, 4 P 2 = 12 5 P 3 = 60, 5 P 3 = 60 6 P 4 = 360, 6 P 4 = 360 7 P 5 = 2520, 7 P 5 = 2520 8 P 6 = 20160, 8 P 6 = 20160 9 P 7 = 181440, 9 P 6 = 60480 10 P 8 = 1814400, 10 P 7 = 604800 11 P 9 = 19958400, 11 P 8 = 6652800 12 P 10 = 239500800, 12 P 9 = 79833600 A sample of Combinations from 10 to 60: (10 C 8) = 45, (10 C 7) = 120 (20 C 18) = 190, (20 C 16) = 4845 (30 C 28) = 435, (30 C 25) = 142506 (40 C 38) = 780, (40 C 34) = 3838380 (50 C 48) = 1225, (50 C 43) = 99884400 (60 C 58) = 1770, (60 C 53) = 386206920 A sample of Permutations from 5 to 15000: 5 P 3 = 6.0000000000e1, 5 P 3 = 6.0000000000e1 15 P 13 = 6.538371840e11, 15 P 12 = 2.179457280e11 25 P 23 = 7.755605022e24, 25 P 20 = 1.292600837e23 35 P 33 = 5.166573983e39, 35 P 30 = 8.610956639e37 45 P 43 = 5.981111043e55, 45 P 39 = 1.661419734e53 55 P 53 = 6.348201677e72, 55 P 48 = 2.519127650e69 65 P 63 = 4.123825296e90, 65 P 57 = 2.045548262e86 75 P 73 = 1.24045704e109, 75 P 67 = 6.15306072e104 85 P 83 = 1.40855206e128, 85 P 76 = 7.76318374e122 95 P 93 = 5.16498924e147, 95 P 86 = 2.84666515e142 105 P 103 = 5.40698379e167, 105 P 95 = 2.98003957e161 115 P 113 = 1.46254685e188, 115 P 105 = 8.06077407e181 125 P 123 = 9.41338588e208, 125 P 114 = 4.71650327e201 135 P 133 = 1.34523635e230, 135 P 124 = 6.74020139e222 145 P 143 = 4.02396303e251, 145 P 133 = 1.68014597e243 A sample of Combinations from 10 to 190: (100 C 98) = 4950.0, (100 C 90) = 17310309456438.8 (200 C 198) = 19900.0, (200 C 186) = 1179791641436960000000.0 (300 C 298) = 44850.0, (300 C 283) = 2287708142022840000000000000.0 (400 C 398) = 79800.0, (400 C 380) = 2788360983670300000000000000000000.0 (500 C 498) = 124750.0, (500 C 478) = 132736424690773000000000000000000000000.0 (600 C 598) = 179700.0, (600 C 576) = 4791686682467800000000000000000000000000000.0 (700 C 698) = 244650.0, (700 C 674) = 145478651313640000000000000000000000000000000000.0 (800 C 798) = 319600.0, (800 C 772) = 3933526871034430000000000000000000000000000000000000.0 (900 C 898) = 404550.0, (900 C 870) = 98033481673646900000000000000000000000000000000000000000.0 (1000 C 998) = 499500.0, (1000 C 969) = 76023224077705100000000000000000000000000000000000000000000.0
Arturo
printPermutations: function [s,b][
print [
"P(" ++ (to :string s) ++ ", " ++ (to :string b) ++ ") = "
permutate.count.by:b @1..s
]
]
printCombinations: function [s,b][
print [
"C(" ++ (to :string s) ++ ", " ++ (to :string b) ++ ") = "
combine.count.by:b @1..s
]
]
printPermutations 4 2
printPermutations 5 3
printPermutations 6 4
printPermutations 7 5
printPermutations 8 6
printPermutations 9 7
printPermutations 10 8
printPermutations 11 9
printPermutations 12 10
printCombinations 10 8
printCombinations 20 18
printCombinations 30 28
printCombinations 40 38
printCombinations 50 48
printCombinations 60 58
printPermutations 340 230
printPermutations 12503 150
printCombinations 180 40
printCombinations 970 730
- Output:
P(4, 2) = 12 P(5, 3) = 60 P(6, 4) = 360 P(7, 5) = 2520 P(8, 6) = 20160 P(9, 7) = 181440 P(10, 8) = 1814400 P(11, 9) = 19958400 P(12, 10) = 239500800 C(10, 8) = 45 C(20, 18) = 190 C(30, 28) = 435 C(40, 38) = 780 C(50, 48) = 1225 C(60, 58) = 1770 P(340, 230) = 321163468667018390278490855166116943643915115883733627394541858241858716874364895663708654024956544433526906929220370657178037367849691887585605027786348781323683175128970012088045935740649918420588744620257725216845699632806302776510600871474726786041782200035955935929612857643030896557053167285732409630111804341546261862735713347179073784452257244336775041366281305006608295780372754879670614948719662927123558774623452956076264437724405141046975318837351290035912604435611648000000000000000000000000000000000000000000000000000000000 P(12503, 150) = 145349029342353586631193854127379263889050707122840603258866143765734805000836318095430535878283222399986691383724192776832431401841845807936456562635873483263903741650446537273646795588914347285406358840689987529465482210964310466322364415189531610901593861947474126246323721536314280740814336769614384426370056684232165925069433834623283158338231715677812329656785966269970444585319639178491261742879187758508103438009278190651455732354378754778290406101258502700133885808094777181331499601845451634234055547273229226095279158651885556410705696845808314349918299242931159040000000000000000000000000000000000000000 C(180, 40) = 18290112128130495302949953479795255876590 C(970, 730) = 1460703798049835817371501066063364773159305309662093793682805325059313312798468600051903640905890411826065678898559485932184945661085268182815842989416642105002033447941384758262043195945021701492825484266010877073654424416642736902160
Bracmat
This solution shows results from bignum as well as floating point implementations. If bignum answers are very big, only the first 50 digits and a count of the digits that are not shown are shown. The bignum answers are shown as Cn and Pn, while the floating point answers are shown as Cf and Pf. Answers are aligned to make it easy to compare the decimals.
( C
= n k coef
. !arg:(?n,?k)
& (!n+-1*!k:<!k:?k|)
& 1:?coef
& whl
' ( !k:>0
& !coef*!n*!k^-1:?coef
& !k+-1:?k
& !n+-1:?n
)
& !coef
)
& ( compileBinomialFunctionThatDoesFloatingPointCalculations
=
. new
$ ( UFP
,
' ( (s.n) (s.k)
. "**************************************************************
*** Notice the difference between the following four lines ***
*** of code and the much shorter (!n+-1*!k:<!k:?k|) in ***
*** function C above. UFP grammar is simpler than usual ***
*** Bracmat grammar. UFP code is therefore less terse. ***
**************************************************************"
& !n+-1*!k:?n-k
& ( !n-k:<!k&!n-k:?k
|
)
& 1:?coef
& whl
' ( !k:>0
& !coef*!n*!k^-1:?coef
& !k+-1:?k
& !n+-1:?n
)
& !coef
)
)
)
& compileBinomialFunctionThatDoesFloatingPointCalculations$
: ?binom
& ( P
= n k result
. !arg:(?n,?k)
& !n+-1*!k:?k
& 1:?result
& whl
' ( !n:>!k
& !n*!result:?result
& !n+-1:?n
)
& !result
)
& ( compilePermutationFunctionThatDoesFloatingPointCalculations
=
. new
$ ( UFP
,
' ( (s.n) (s.k)
. !n+-1*!k:?k
& 1:?result
& whl
' ( !n:>!k
& !n*!result:?result
& !n+-1:?n
)
& !result
)
)
)
& compilePermutationFunctionThatDoesFloatingPointCalculations$
: ?permu
& 0:?i
& whl
' ( 1+!i:~>12:?i
& div$(!i.3):?k
& out$(!i P !k "=" P$(!i,!k))
)
& 0:?i
& whl
' ( 10+!i:~>60:?i
& div$(!i.3):?k
& out$(!i Cn !k "= " C$(!i,!k))
& out$(!i Cf !k "=" (binom..go)$(!i,!k))
)
& ( displayBig
=
. @(!arg:?show [50 ? [?length)
& !show "... (" !length+-50 " more digits)"
| !arg
)
& 5 50 500 1000 5000 15000:?is
& whl
' ( !is:%?i ?is
& div$(!i.3):?k
& out
$ ( str
$ (!i " Pn " !k " = " displayBig$(P$(!i,!k)))
)
& out
$ ( str
$ (!i " Pf " !k " = " (permu..go)$(!i,!k))
)
)
& 0:?i
& whl
' ( 100+!i:~>1000:?i
& div$(!i.3):?k
& out
$ ( str
$ (!i " Cn " !k " = " displayBig$(C$(!i,!k)))
)
& out
$ ( str
$ (!i " Cf " !k " = " (binom..go)$(!i,!k))
)
)
& all done;
Output:
1 P 0 = 1 2 P 0 = 1 3 P 1 = 3 4 P 1 = 4 5 P 1 = 5 6 P 2 = 30 7 P 2 = 42 8 P 2 = 56 9 P 3 = 504 10 P 3 = 720 11 P 3 = 990 12 P 4 = 11880 10 Cn 3 = 120 10 Cf 3 = 1.1999999999999999E+02 20 Cn 6 = 38760 20 Cf 6 = 3.8759999999999993E+04 30 Cn 10 = 30045015 30 Cf 10 = 3.0045014999999989E+07 40 Cn 13 = 12033222880 40 Cf 13 = 1.2033222880000000E+10 50 Cn 16 = 4923689695575 50 Cf 16 = 4.9236896955750000E+12 60 Cn 20 = 4191844505805495 60 Cf 20 = 4.1918445058054930E+15 5 Pn 1 = 5 5 Pf 1 = 5.0000000000000000E+00 50 Pn 16 = 103017324974226408345600000 50 Pf 16 = 1.0301732497422640E+26 500 Pn 166 = 35348749217429427876093618266017623068440028791060... (385 more digits) 500 Pf 166 = INF 1000 Pn 333 = 59693262885034150890397017659007842809981894765670... (922 more digits) 1000 Pf 333 = INF 5000 Pn 1666 = 68567457572556742754845369402488960622341567102448... (5976 more digits) 5000 Pf 1666 = INF 15000 Pn 5000 = 96498539887274939220148588059312959807922816886808... (20420 more digits) 15000 Pf 5000 = INF 100 Cn 33 = 294692427022540894366527900 100 Cf 33 = 2.9469242702254079E+26 200 Cn 66 = 72697525451692783415270666511927389767550269141935... (4 more digits) 200 Cf 66 = 7.2697525451692816E+53 300 Cn 100 = 41582514632585647447833835263264055802804660057436... (32 more digits) 300 Cf 100 = 4.1582514632585569E+81 400 Cn 133 = 12579486841821087021333484756519650044917494358375... (60 more digits) 400 Cf 133 = 1.2579486841821091E+109 500 Cn 166 = 39260283861944227552204083450723314281973490135301... (87 more digits) 500 Cf 166 = 3.9260283861944195E+136 600 Cn 200 = 25060177832214028050056167705132288352025510250879... (115 more digits) 600 Cf 200 = 2.5060177832213946E+164 700 Cn 233 = 81032035633395999047404536440311382329449203119421... (142 more digits) 700 Cf 233 = 8.1032035633395859E+191 800 Cn 266 = 26456233626836270342888292995561242550915240450150... (170 more digits) 800 Cf 266 = 2.6456233626836295E+219 900 Cn 300 = 17433563732964466429607307650857183476303419689548... (198 more digits) 900 Cf 300 = 1.7433563732964451E+247 1000 Cn 333 = 57761345531476516697774863235496017223394580195002... (225 more digits) 1000 Cf 333 = 5.7761345531476355E+274 {!} all done
C
Using big integers. GMP in fact has a factorial function which is quite possibly more efficient, though using it would make code longer.
#include <gmp.h>
void perm(mpz_t out, int n, int k)
{
mpz_set_ui(out, 1);
k = n - k;
while (n > k) mpz_mul_ui(out, out, n--);
}
void comb(mpz_t out, int n, int k)
{
perm(out, n, k);
while (k) mpz_divexact_ui(out, out, k--);
}
int main(void)
{
mpz_t x;
mpz_init(x);
perm(x, 1000, 969);
gmp_printf("P(1000,969) = %Zd\n", x);
comb(x, 1000, 969);
gmp_printf("C(1000,969) = %Zd\n", x);
return 0;
}
C#
using System;
using System.Numerics;
class CombinationsAndPermutations
{
public static void Main(string[] args)
{
Console.WriteLine(double.MaxValue);
Console.WriteLine("A sample of permutations from 1 to 12 with exact Integer arithmetic:");
for (int n = 1; n <= 12; n++)
{
int k = n / 2;
Console.WriteLine($"{n} P {k} = {Permutation(n, k)}");
}
Console.WriteLine();
Console.WriteLine("A sample of combinations from 10 to 60 with exact Integer arithmetic:");
for (int n = 10; n <= 60; n += 5)
{
int k = n / 2;
Console.WriteLine($"{n} C {k} = {Combination(n, k)}");
}
Console.WriteLine();
Console.WriteLine("A sample of permutations from 5 to 15000 displayed in floating point arithmetic:");
Console.WriteLine($"{5} P {2} = {Display(Permutation(5, 2), 50)}");
for (int n = 1000; n <= 15000; n += 1000)
{
int k = n / 2;
Console.WriteLine($"{n} P {k} = {Display(Permutation(n, k), 50)}");
}
Console.WriteLine();
Console.WriteLine("A sample of combinations from 100 to 1000 displayed in floating point arithmetic:");
for (int n = 100; n <= 1000; n += 100)
{
int k = n / 2;
Console.WriteLine($"{n} C {k} = {Display(Combination(n, k), 50)}");
}
}
private static string Display(BigInteger val, int precision)
{
string s = val.ToString();
// Ensure that we don't try to take a substring longer than what's available.
int actualPrecision = Math.Min(precision, s.Length - 1); // Adjusted to ensure it doesn't exceed string length
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (s.Length > 1) // Check if the string has more than one character
{
sb.Append(s.Substring(0, 1));
sb.Append(".");
sb.Append(s.Substring(1, actualPrecision-1));
}
else
{
// If the string is only one digit, no need to insert a decimal point.
sb.Append(s);
}
sb.Append(" * 10^");
sb.Append(s.Length - 1);
return sb.ToString();
}
public static BigInteger Combination(int n, int k)
{
// Select value with smallest intermediate results
// combination(n, k) = combination(n, n-k)
if (n - k < k)
{
k = n - k;
}
BigInteger result = Permutation(n, k);
while (k > 0)
{
result = result / k;
k--;
}
return result;
}
public static BigInteger Permutation(int n, int k)
{
BigInteger result = BigInteger.One;
for (int i = n; i >= n - k + 1; i--)
{
result = result * i;
}
return result;
}
}
- Output:
1.79769313486232E+308 A sample of permutations from 1 to 12 with exact Integer arithmetic: 1 P 0 = 1 2 P 1 = 2 3 P 1 = 3 4 P 2 = 12 5 P 2 = 20 6 P 3 = 120 7 P 3 = 210 8 P 4 = 1680 9 P 4 = 3024 10 P 5 = 30240 11 P 5 = 55440 12 P 6 = 665280 A sample of combinations from 10 to 60 with exact Integer arithmetic: 10 C 5 = 252 15 C 7 = 6435 20 C 10 = 184756 25 C 12 = 5200300 30 C 15 = 155117520 35 C 17 = 4537567650 40 C 20 = 137846528820 45 C 22 = 4116715363800 50 C 25 = 126410606437752 55 C 27 = 3824345300380220 60 C 30 = 118264581564861424 A sample of permutations from 5 to 15000 displayed in floating point arithmetic: 5 P 2 = 2. * 10^1 1000 P 500 = 3.2978863640988537122024252070116261706996485697981 * 10^1433 2000 P 1000 = 8.2415012140674255266380217928953202425839550211348 * 10^3167 3000 P 1500 = 8.6229457673788561572282325050469704818001698192368 * 10^5015 4000 P 2000 = 5.5146268042637929575202252487087217092097210095831 * 10^6937 5000 P 2500 = 2.5959899179479570425022364594725223975158226787173 * 10^8914 6000 P 3000 = 6.4684674799045492726351265543133876130483115297807 * 10^10934 7000 P 3500 = 3.6978393541988590953223392044469547113117500019066 * 10^12991 8000 P 4000 = 2.8347416494109128583587900207169062803923698647730 * 10^15079 9000 P 4500 = 3.5613559022062915735922606191272180393638776777367 * 10^17194 10000 P 5000 = 6.7310091721588924046678115055013992269082753633190 * 10^19333 11000 P 5500 = 7.1714299723894354619599359891785521535675525394493 * 10^21494 12000 P 6000 = 4.4778633072110971517945389774618813158941392935141 * 10^23675 13000 P 6500 = 3.6571405647713639990172807053439865891697112165983 * 10^25874 14000 P 7000 = 1.5680448683572888099973548116924953997328821172933 * 10^28090 15000 P 7500 = 2.2454775022523692436484435950526532351441855443096 * 10^30321 A sample of combinations from 100 to 1000 displayed in floating point arithmetic: 100 C 50 = 1.0089134454556419333481249725 * 10^29 200 C 100 = 9.0548514656103281165404177077484163874504589675413 * 10^58 300 C 150 = 9.3759702772827452793193754439064084879232655700081 * 10^88 400 C 200 = 1.0295250013541443297297588032040198675721092538107 * 10^119 500 C 250 = 1.1674431578827768292093473476217661965923008118031 * 10^149 600 C 300 = 1.3510794199619426851447487797850453039723394544919 * 10^179 700 C 350 = 1.5857433585316795487607022764754299250587342835720 * 10^209 800 C 400 = 1.8804244186835312700958607615195351332156581822914 * 10^239 900 C 450 = 2.2474718820660159573188913903771345843514101350359 * 10^269 1000 C 500 = 2.7028824094543656951561469362597527549615200844654 * 10^299
C++
Compiled with g++-10 -Wall -std=c++03
, linked with -lgmp
#include <boost/multiprecision/gmp.hpp>
#include <iostream>
using namespace boost::multiprecision;
mpz_int p(uint n, uint p) {
mpz_int r = 1;
mpz_int k = n - p;
while (n > k)
r *= n--;
return r;
}
mpz_int c(uint n, uint k) {
mpz_int r = p(n, k);
while (k)
r /= k--;
return r;
}
int main() {
for (uint i = 1u; i < 12u; i++)
std::cout << "P(12," << i << ") = " << p(12u, i) << std::endl;
for (uint i = 10u; i < 60u; i += 10u)
std::cout << "C(60," << i << ") = " << c(60u, i) << std::endl;
return 0;
}
- Output:
P(12,1) = 12 P(12,2) = 132 P(12,3) = 1320 P(12,4) = 11880 P(12,5) = 95040 P(12,6) = 665280 P(12,7) = 3991680 P(12,8) = 19958400 P(12,9) = 79833600 P(12,10) = 239500800 P(12,11) = 479001600 C(60,10) = 75394027566 C(60,20) = 4191844505805495 C(60,30) = 118264581564861424 C(60,40) = 4191844505805495 C(60,50) = 75394027566
Common Lisp
(defun combinations (n k)
(cond ((or (< n k) (< k 0) (< n 0)) 0)
((= k 0) 1)
(t (do* ((i 1 (1+ i))
(m n (1- m))
(a m (* a m))
(b i (* b i)))
((= i k) (/ a b))))))
(defun permutations (n k)
(cond ((or (< n k) (< k 0) (< n 0)) 0)
((= k 0) 1)
(t (do* ((i 1 (1+ i))
(m n (1- m))
(a m (* a m)))
((= i k) a)))))
Crystal
require "big"
include Math
struct Int
def permutation(k)
(self-k+1..self).product(1.to_big_i)
end
def combination(k)
self.permutation(k) // (1..k).product(1.to_big_i)
end
def big_permutation(k)
exp(lgamma_plus(self) - lgamma_plus(self-k))
end
def big_combination(k)
exp( lgamma_plus(self) - lgamma_plus(self - k) - lgamma_plus(k))
end
private def lgamma_plus(n)
lgamma(n+1) #lgamma is the natural log of gamma
end
end
p 12.permutation(9) #=> 79833600
p 12.big_permutation(9) #=> 79833600.00000021
p 60.combination(53) #=> 386206920
p 145.big_permutation(133) #=> 1.6801459655817956e+243
p 900.big_combination(450) #=> 2.247471882064647e+269
p 1000.big_combination(969) #=> 7.602322407770517e+58
p 15000.big_permutation(73) #=> 6.004137561717704e+304
#That's about the maximum of Float:
p 15000.big_permutation(74) #=> Infinity
#Fixnum has no maximum:
p 15000.permutation(74) #=> 896237613852967826239917238565433149353074416025197784301593335243699358040738127950872384197159884905490054194835376498534786047382445592358843238688903318467070575184552953997615178973027752714539513893159815472948987921587671399790410958903188816684444202526779550201576117111844818124800000000000000000000
- Output:
79833600 79833600.00000021 386206920 1.6801459655817956e+243 2.247471882064647e+269 7.602322407770517e+58 6.004137561717704e+304 Infinity 896237613852967826239917238565433149353074416025197784301593335243699358040738127950872384197159884905490054194835376498534786047382445592358843238688903318467070575184552953997615178973027752714539513893159815472948987921587671399790410958903188816684444202526779550201576117111844818124800000000000000000000
D
import std.stdio, std.mathspecial, std.range, std.algorithm,
std.bigint, std.conv;
enum permutation = (in uint n, in uint k) pure =>
reduce!q{a * b}(1.BigInt, iota(n - k + 1, n + 1));
enum combination = (in uint n, in uint k) pure =>
n.permutation(k) / reduce!q{a * b}(1.BigInt, iota(1, k + 1));
enum bigPermutation = (in uint n, in uint k) =>
exp(logGamma(n + 1) - logGamma(n - k + 1));
enum bigCombination = (in uint n, in uint k) =>
exp(logGamma(n + 1) - logGamma(n - k + 1) - logGamma(k + 1));
void main() {
12.permutation(9).writeln;
12.bigPermutation(9).writeln;
60.combination(53).writeln;
145.bigPermutation(133).writeln;
900.bigCombination(450).writeln;
1_000.bigCombination(969).writeln;
15_000.bigPermutation(73).writeln;
15_000.bigPermutation(1185).writeln;
writefln("%(%s\\\n%)", 15_000.permutation(74).text.chunks(50));
}
- Output:
79833600 7.98336e+07 386206920 1.68015e+243 2.24747e+269 7.60232e+58 6.00414e+304 6.31335e+4927 89623761385296782623991723856543314935307441602519\ 77843015933352436993580407381279508723841971598849\ 05490054194835376498534786047382445592358843238688\ 90331846707057518455295399761517897302775271453951\ 38931598154729489879215876713997904109589031888166\ 84444202526779550201576117111844818124800000000000\ 000000000
EasyLang
func perm x y .
z = 1
for i = x - y + 1 to x
z *= i
.
return z
.
func fact x .
z = 1
for i = 2 to x
z *= i
.
return z
.
func comb x y .
if x - y < y
y = x - y
.
return perm x y / fact y
.
#
e = 2.7182818284590452354
func log n .
return log10 n / log10 e
.
func lstirling n .
if n < 10
return lstirling (n + 1) - log (n + 1)
.
return 0.5 * log (2 * pi * n) + n * log (n / e + 1 / (12 * e * n))
.
func$ tolog v .
h = v div log 10
return pow e (v - h * log 10) & "e" & h
.
func$ permf n k .
return tolog (lstirling n - lstirling (n - k))
.
func$ combf n k .
return tolog (lstirling n - lstirling (n - k) - lstirling k)
.
print "=> Exact results:"
for n = 1 to 12
p = n div 3
print "P(" & n & "," & p & ")=" & perm n p
.
#
# double has 53 bits for integer
#
for n = 10 step 10 to 50
p = n div 3
print "C(" & n & "," & p & ")=" & comb n p
.
#
print ""
print "=> Floating point approximations:"
for n in [ 5 50 500 1000 5000 15000 ]
p = n div 3
print "P(" & n & "," & p & ")=" & permf n p
.
for n = 100 step 100 to 1000
p = n div 3
print "C(" & n & "," & p & ")=" & combf n p
.
EchoLisp
;; rename native functions according to task
(define-syntax-rule (Cnk n k) (Cnp n k))
(define-syntax-rule (Ank n k) (Anp n k))
(Cnk 10 1)
→ 10
(lib 'bigint) ;; no floating point needed : use large integers
(Cnk 100 10)
→ 17310309456440
(Cnk 1000 42)
→ 297242911333923795640059429176065863139989673213703918037987737481286092000
(Ank 10 10)
→ 3628800
(factorial 10)
→ 3628800
(Ank 666 42)
→ 1029024198692120734765388598788124551227594950478035495578451793852872815678512303375588360
1398831219998720000000000000
Elixir
defmodule Combinations_permutations do
def perm(n, k), do: product(n - k + 1 .. n)
def comb(n, k), do: div( perm(n, k), product(1 .. k) )
defp product(a..b) when a>b, do: 1
defp product(list), do: Enum.reduce(list, 1, fn n, acc -> n * acc end)
def test do
IO.puts "\nA sample of permutations from 1 to 12:"
Enum.each(1..12, &show_perm(&1, div(&1, 3)))
IO.puts "\nA sample of combinations from 10 to 60:"
Enum.take_every(10..60, 10) |> Enum.each(&show_comb(&1, div(&1, 3)))
IO.puts "\nA sample of permutations from 5 to 15000:"
Enum.each([5,50,500,1000,5000,15000], &show_perm(&1, div(&1, 3)))
IO.puts "\nA sample of combinations from 100 to 1000:"
Enum.take_every(100..1000, 100) |> Enum.each(&show_comb(&1, div(&1, 3)))
end
defp show_perm(n, k), do: show_gen(n, k, "perm", &perm/2)
defp show_comb(n, k), do: show_gen(n, k, "comb", &comb/2)
defp show_gen(n, k, strfun, fun), do:
IO.puts "#{strfun}(#{n}, #{k}) = #{show_big(fun.(n, k), 40)}"
defp show_big(n, limit) do
strn = to_string(n)
if String.length(strn) < limit do
strn
else
{shown, hidden} = String.split_at(strn, limit)
"#{shown}... (#{String.length(hidden)} more digits)"
end
end
end
Combinations_permutations.test
- Output:
A sample of permutations from 1 to 12: perm(1, 0) = 1 perm(2, 0) = 1 perm(3, 1) = 3 perm(4, 1) = 4 perm(5, 1) = 5 perm(6, 2) = 30 perm(7, 2) = 42 perm(8, 2) = 56 perm(9, 3) = 504 perm(10, 3) = 720 perm(11, 3) = 990 perm(12, 4) = 11880 A sample of combinations from 10 to 60: comb(10, 3) = 120 comb(20, 6) = 38760 comb(30, 10) = 30045015 comb(40, 13) = 12033222880 comb(50, 16) = 4923689695575 comb(60, 20) = 4191844505805495 A sample of permutations from 5 to 15000: perm(5, 1) = 5 perm(50, 16) = 103017324974226408345600000 perm(500, 166) = 3534874921742942787609361826601762306844... (395 more digits) perm(1000, 333) = 5969326288503415089039701765900784280998... (932 more digits) perm(5000, 1666) = 6856745757255674275484536940248896062234... (5986 more digits) perm(15000, 5000) = 9649853988727493922014858805931295980792... (20430 more digits) A sample of combinations from 100 to 1000: comb(100, 33) = 294692427022540894366527900 comb(200, 66) = 7269752545169278341527066651192738976755... (14 more digits) comb(300, 100) = 4158251463258564744783383526326405580280... (42 more digits) comb(400, 133) = 1257948684182108702133348475651965004491... (70 more digits) comb(500, 166) = 3926028386194422755220408345072331428197... (97 more digits) comb(600, 200) = 2506017783221402805005616770513228835202... (125 more digits) comb(700, 233) = 8103203563339599904740453644031138232944... (152 more digits) comb(800, 266) = 2645623362683627034288829299556124255091... (180 more digits) comb(900, 300) = 1743356373296446642960730765085718347630... (208 more digits) comb(1000, 333) = 5776134553147651669777486323549601722339... (235 more digits)
Erlang
-module(combinations_permutations).
-export([test/0]).
perm(N, K) ->
product(lists:seq(N - K + 1, N)).
comb(N, K) ->
perm(N, K) div product(lists:seq(1, K)).
product(List) ->
lists:foldl(fun(N, Acc) -> N * Acc end, 1, List).
test() ->
io:format("\nA sample of permutations from 1 to 12:\n"),
[show_perm({N, N div 3}) || N <- lists:seq(1, 12)],
io:format("\nA sample of combinations from 10 to 60:\n"),
[show_comb({N, N div 3}) || N <- lists:seq(10, 60, 10)],
io:format("\nA sample of permutations from 5 to 15000:\n"),
[show_perm({N, N div 3}) || N <- [5,50,500,1000,5000,15000]],
io:format("\nA sample of combinations from 100 to 1000:\n"),
[show_comb({N, N div 3}) || N <- lists:seq(100, 1000, 100)],
ok.
show_perm({N, K}) ->
show_gen(N, K, "perm", fun perm/2).
show_comb({N, K}) ->
show_gen(N, K, "comb", fun comb/2).
show_gen(N, K, StrFun, Fun) ->
io:format("~s(~p, ~p) = ~s\n",[StrFun, N, K, show_big(Fun(N, K), 40)]).
show_big(N, Limit) ->
StrN = integer_to_list(N),
case length(StrN) < Limit of
true ->
StrN;
false ->
{Shown, Hidden} = lists:split(Limit, StrN),
io_lib:format("~s... (~p more digits)", [Shown, length(Hidden)])
end.
Output:
A sample of permutations from 1 to 12: perm(1, 0) = 1 perm(2, 0) = 1 perm(3, 1) = 3 perm(4, 1) = 4 perm(5, 1) = 5 perm(6, 2) = 30 perm(7, 2) = 42 perm(8, 2) = 56 perm(9, 3) = 504 perm(10, 3) = 720 perm(11, 3) = 990 perm(12, 4) = 11880 A sample of combinations from 10 to 60: comb(10, 3) = 120 comb(20, 6) = 38760 comb(30, 10) = 30045015 comb(40, 13) = 12033222880 comb(50, 16) = 4923689695575 comb(60, 20) = 4191844505805495 A sample of permutations from 5 to 15000: perm(5, 1) = 5 perm(50, 16) = 103017324974226408345600000 perm(500, 166) = 3534874921742942787609361826601762306844... (395 more digits) perm(1000, 333) = 5969326288503415089039701765900784280998... (932 more digits) perm(5000, 1666) = 6856745757255674275484536940248896062234... (5986 more digits) perm(15000, 5000) = 9649853988727493922014858805931295980792... (20430 more digits) A sample of combinations from 100 to 1000: comb(100, 33) = 294692427022540894366527900 comb(200, 66) = 7269752545169278341527066651192738976755... (14 more digits) comb(300, 100) = 4158251463258564744783383526326405580280... (42 more digits) comb(400, 133) = 1257948684182108702133348475651965004491... (70 more digits) comb(500, 166) = 3926028386194422755220408345072331428197... (97 more digits) comb(600, 200) = 2506017783221402805005616770513228835202... (125 more digits) comb(700, 233) = 8103203563339599904740453644031138232944... (152 more digits) comb(800, 266) = 2645623362683627034288829299556124255091... (180 more digits) comb(900, 300) = 1743356373296446642960730765085718347630... (208 more digits) comb(1000, 333) = 5776134553147651669777486323549601722339... (235 more digits)
Factor
As with Racket, these operations are built in and Factor has unlimited integers.
USING: math.combinatorics prettyprint ;
1000 10 nCk . ! 263409560461970212832400
1000 10 nPk . ! 955860613004397508326213120000
FreeBASIC
Function PermBig(x As Long, y As Long) As ULongint
Dim As Long i
Dim As Longint z = 1
For i = x - y + 1 To x
z = z * i
Next i
Return (z)
End Function
Function FactBig(x As Long) As ULongint
Dim As Long i
Dim As Longint z = 1
For i = 2 To x
z = z * i
Next i
Return (z)
End Function
Function CombBig(Byval x As Long, Byval y As Long) As Double
If y > x Then
Return (0)
Elseif x = y Then
Return (1)
Else
If x - y < y Then y = x - y
Return (PermBig(x, y) / FactBig(y))
End If
End Function
Dim As Long i, j
Print "-- Long Integer - Permutations - from 1 to 12"
For i = 1 To 12
For j = 1 To i
Print "P(" & i & "," & j & ")=" & Str(PermBig(i, j)) & " ";
Next j
Print ""
Next i
Print Chr(10) & "-- Float integer - Combinations from 10 to 60"
For i = 10 To 60 Step 10
For j = 1 To i Step i \ 5
Print "C(" & i & "," & j & ")=" & Str(CombBig(i, j)) & " ";
Next j
Print ""
Next i
Print Chr(10) & "-- Float integer - Permutations from 5000 to 15000"
For i = 5000 To 15000 Step 5000
For j = 10 To 50 Step 20
Print "P(" & i & "," & j & ")=" & Str(PermBig(i, j)) & " ";
Next j
Print ""
Next i
Print Chr(10) & "-- Float integer - Combinations from 200 to 1000"
For i = 200 To 1000 Step 200
For j = 20 To 100 Step 20
Print "C(" & i & "," & j & ")=" & Str(CombBig(i, j)) & " ";
Next j
Print ""
Next i
Sleep
Go
Go has arbitrary-length maths in the standard math/big library; no need for floating-point approximations at this level.
package main
import (
"fmt"
"math/big"
)
func main() {
var n, p int64
fmt.Printf("A sample of permutations from 1 to 12:\n")
for n = 1; n < 13; n++ {
p = n / 3
fmt.Printf("P(%d,%d) = %d\n", n, p, perm(big.NewInt(n), big.NewInt(p)))
}
fmt.Printf("\nA sample of combinations from 10 to 60:\n")
for n = 10; n < 61; n += 10 {
p = n / 3
fmt.Printf("C(%d,%d) = %d\n", n, p, comb(big.NewInt(n), big.NewInt(p)))
}
fmt.Printf("\nA sample of permutations from 5 to 15000:\n")
nArr := [...]int64{5, 50, 500, 1000, 5000, 15000}
for _, n = range nArr {
p = n / 3
fmt.Printf("P(%d,%d) = %d\n", n, p, perm(big.NewInt(n), big.NewInt(p)))
}
fmt.Printf("\nA sample of combinations from 100 to 1000:\n")
for n = 100; n < 1001; n += 100 {
p = n / 3
fmt.Printf("C(%d,%d) = %d\n", n, p, comb(big.NewInt(n), big.NewInt(p)))
}
}
func fact(n *big.Int) *big.Int {
if n.Sign() < 1 {
return big.NewInt(0)
}
r := big.NewInt(1)
i := big.NewInt(2)
for i.Cmp(n) < 1 {
r.Mul(r, i)
i.Add(i, big.NewInt(1))
}
return r
}
func perm(n, k *big.Int) *big.Int {
r := fact(n)
r.Div(r, fact(n.Sub(n, k)))
return r
}
func comb(n, r *big.Int) *big.Int {
if r.Cmp(n) == 1 {
return big.NewInt(0)
}
if r.Cmp(n) == 0 {
return big.NewInt(1)
}
c := fact(n)
den := fact(n.Sub(n, r))
den.Mul(den, fact(r))
c.Div(c, den)
return c
}
Output:
A sample of permutations from 1 to 12: P(1,0) = 1 P(2,0) = 1 P(3,1) = 3 P(4,1) = 4 P(5,1) = 5 P(6,2) = 30 P(7,2) = 42 P(8,2) = 56 P(9,3) = 504 P(10,3) = 720 P(11,3) = 990 P(12,4) = 11880 A sample of combinations from 10 to 60: C(10,3) = 120 C(20,6) = 38760 C(30,10) = 30045015 C(40,13) = 12033222880 C(50,16) = 4923689695575 C(60,20) = 4191844505805495 A sample of permutations from 5 to 15000: P(5,1) = 5 P(50,16) = 103017324974226408345600000 P(500,166) = 353487492174294278760936182660176230684400287910609032932176169251145051223056590013516735448538086130105926216996155913554025250125337170813019594283712354977999534430770809915541863294344717641926832713607917635838943102385935821177067602075180371673503765613359169210620516084434587852075431010684540863423686685437846488590916158047347611875355166780660833377163468853354607169353747005440000000000000000000000000000000000000000000 P(1000,333) = 596932628850341508903970176590078428099818947656708993181003187015748137551596090897395098770177006143741943000028735297176540996715216223470117008188290845824893667956971794591724165149886070514986743432208287422668258597883938335639789463537748828480742878588232053442156529356123644254034620250998013239063050800571901268462622323786888857845397534124006543754044331948142416200311556601875197681493636464229808874876131434533721937546154413110195799580966669097512255452752067457629468146295647406985227990184437533735467426422585063839734564755495294687791091277426861971582062496498138090957027659529000216472781766770467939751274131497380920782541878343751496719223481266229644276166815775979972070711062842180838624567600323874889368489920534418201154996144776696986749038638993937273035934558675329887334851616951614782042039326589303359315137179445599073086196250614391361241088000000000000000000000000000000000000000000000000000000000000000000000000000000000000 P(5000,1666) = 685674575725567427548453694024889606223415671024481949274389525763165050940278456955930987049278913288741555958551429473866794447094151777406284837935079289013939976368320856320075398810321021264609367677596630017492662476653457696667818345302032079158497998678962485919859205035598026552321633034034950067207086196635562039504231368320682342175536748176816241129369211418155064764285518551122913802314264757797230065345837585112169021234001053819461909997341171332285483908469793127022101882927191957584158820572953454348525922376264896938701700503579[cut for brevity] P(15000,5000) = 964985398872749392201485880593129598079228168868086089709069882934904327326041434448685068557423519588782990996839148935743422697293448340149394869739166392123184483900811562453898657822593544251663672426442538772790754374376708208571908721887559582227891355612508675254239851818491849618848602192999811776790423150460291684931309968390568370095954400889615967984376006072547506893620140168365357740946620575769516153753735678390720704316317251046076250691800213698137901479234159657387339301806781869228964210268691780310799227446113809960921205463002689680686581917548426454723087176124161728203856922785131850458595700123281745279678944233081992533251647291980003523846698046974475328766195265764029672828687155439288711515137638802309221117722696141292043413736618293499869841412502567093112620576877254953509763190120514494690844850900732795773648193199871673637389424514221019995024902360799221264651063770768194819355718580618775786102220736660007307021195929713637615667876228769039112504881578385857681786265840651390718446642041061982261630233585694136722143048873223923363402206453540375800805584706454386378553117095912890292078608807203370350094921116703330118357576158786202069866488676813049328910886961677198798213135372964228023956951408480830806905842004749290253667472325116488994202675719755525469268037451046892994419861436389890344224919839492952550142350743[cut for brevity] A sample of combinations from 100 to 1000: C(100,33) = 294692427022540894366527900 C(200,66) = 726975254516927834152706665119273897675502691419359300 C(300,100) = 4158251463258564744783383526326405580280466005743648708663033657304756328324008620 C(400,133) = 12579486841821087021333484756519650044917494358375678689903944407062661887691782714561293494166382210572895600 C(500,166) = 39260283861944227552204083450723314281973490135301528555644859907093815055309467400410307687655531369748267877388321068535356654999949000 C(600,200) = 250601778322140280500561677051322883520255102508793389473094343332441398315528846878026090182866148274621477126087990864486283260622128340138769443055475567389095596 C(700,233) = 810320356333959990474045364403113823294492031194214481466666874664632951279413378341573227990559808332117096088495529108312831240206642074673862825014526456696556162909686658807978793453220000 C(800,266) = 2645623362683627034288829299556124255091524045015061559880110850588357798837813526621954238671844949835878984342140544523564918954064307529607727040078866833961879433579846596361407958192581870170248962672479120257018000 C(900,300) = 17433563732964466429607307650857183476303419689548896834573896609295907147982188408607179689430757813632301567003238290404591375673438892792913992016448098783043956457942357838233534288303678577768883350818012950587783262800434058273110416350965200 C(1000,333) = 57761345531476516697774863235496017223394580195002114171799054793660405129610824218694609475292335509897216233568933163108481350037180876217607177657236327948642711456536116349650593787069554795812874358426845137087373717847050642650744775784499136594696491030795647099932000
Haskell
The Haskell Integer type supports arbitrary precision so floating point approximation is not needed.
perm :: Integer -> Integer -> Integer
perm n k = product [n-k+1..n]
comb :: Integer -> Integer -> Integer
comb n k = perm n k `div` product [1..k]
main :: IO ()
main = do
let showBig maxlen b =
let st = show b
stlen = length st
in if stlen < maxlen then st else take maxlen st ++ "... (" ++ show (stlen-maxlen) ++ " more digits)"
let showPerm pr =
putStrLn $ "perm(" ++ show n ++ "," ++ show k ++ ") = " ++ showBig 40 (perm n k)
where n = fst pr
k = snd pr
let showComb pr =
putStrLn $ "comb(" ++ show n ++ "," ++ show k ++ ") = " ++ showBig 40 (comb n k)
where n = fst pr
k = snd pr
putStrLn "A sample of permutations from 1 to 12:"
mapM_ showPerm [(n, n `div` 3) | n <- [1..12] ]
putStrLn ""
putStrLn "A sample of combinations from 10 to 60:"
mapM_ showComb [(n, n `div` 3) | n <- [10,20..60] ]
putStrLn ""
putStrLn "A sample of permutations from 5 to 15000:"
mapM_ showPerm [(n, n `div` 3) | n <- [5,50,500,1000,5000,15000] ]
putStrLn ""
putStrLn "A sample of combinations from 100 to 1000:"
mapM_ showComb [(n, n `div` 3) | n <- [100,200..1000] ]
- Output:
A sample of permutations from 1 to 12: perm(1,0) = 1 perm(2,0) = 1 perm(3,1) = 3 perm(4,1) = 4 perm(5,1) = 5 perm(6,2) = 30 perm(7,2) = 42 perm(8,2) = 56 perm(9,3) = 504 perm(10,3) = 720 perm(11,3) = 990 perm(12,4) = 11880 A sample of combinations from 10 to 60: comb(10,3) = 120 comb(20,6) = 38760 comb(30,10) = 30045015 comb(40,13) = 12033222880 comb(50,16) = 4923689695575 comb(60,20) = 4191844505805495 A sample of permutations from 5 to 15000: perm(5,1) = 5 perm(50,16) = 103017324974226408345600000 perm(500,166) = 3534874921742942787609361826601762306844... (395 more digits) perm(1000,333) = 5969326288503415089039701765900784280998... (932 more digits) perm(5000,1666) = 6856745757255674275484536940248896062234... (5986 more digits) perm(15000,5000) = 9649853988727493922014858805931295980792... (20430 more digits) A sample of combinations from 100 to 1000: comb(100,33) = 294692427022540894366527900 comb(200,66) = 7269752545169278341527066651192738976755... (14 more digits) comb(300,100) = 4158251463258564744783383526326405580280... (42 more digits) comb(400,133) = 1257948684182108702133348475651965004491... (70 more digits) comb(500,166) = 3926028386194422755220408345072331428197... (97 more digits) comb(600,200) = 2506017783221402805005616770513228835202... (125 more digits) comb(700,233) = 8103203563339599904740453644031138232944... (152 more digits) comb(800,266) = 2645623362683627034288829299556124255091... (180 more digits) comb(900,300) = 1743356373296446642960730765085718347630... (208 more digits) comb(1000,333) = 5776134553147651669777486323549601722339... (235 more digits)
Icon and Unicon
As with several other languages here, Icon and Unicon can handle unlimited integers so floating point approximation isn't needed. The sample here gives a few representative values to shorten the output.
procedure main()
write("P(4,2) = ",P(4,2))
write("P(8,2) = ",P(8,2))
write("P(10,8) = ",P(10,8))
write("C(10,8) = ",C(10,8))
write("C(20,8) = ",C(20,8))
write("C(60,58) = ",C(60,58))
write("P(1000,10) = ",P(1000,10))
write("P(1000,20) = ",P(1000,20))
write("P(15000,2) = ",P(15000,2))
write("C(1000,10) = ",C(1000,10))
write("C(1000,999) = ",C(1000,999))
write("C(1000,1000) = ",C(1000,1000))
write("C(15000,14998) = ",C(15000,14998))
end
procedure C(n,k)
every (d:=1) *:= 2 to k
return P(n,k)/d
end
procedure P(n,k)
every (p:=1) *:= (n-k+1) to n
return p
end
Output:
->cap P(4,2) = 12 P(8,2) = 56 P(10,8) = 1814400 C(10,8) = 45 C(20,8) = 125970 C(60,58) = 1770 P(1000,10) = 955860613004397508326213120000 P(1000,20) = 825928413359200443640727373872992573951185652339949568000000 P(15000,2) = 224985000 C(1000,10) = 263409560461970212832400 C(1000,999) = 1000 C(1000,1000) = 1 C(15000,14998) = 112492500 ->
J
It looks like this task wants a count of the available combinations or permutations (given a set of 3 things, there are three distinct combinations of 2 of them) rather than a representation of the available combinations or permutations (given a set of three things, the distinct combinations of 2 of them may be identified by <0,1>, <0,2> and <1,2>)).
Also, this task allows a language to show off its abilities to support floating point numbers outside the usual range of 64 bit IEEE floating point numbers. We'll neglect that part.
Implementation:
C=: !
P=: (%&!&x:~ * <:)"0
! is a primitive, but we will give it a name (C
) for this task.
Example use (P is permutations, C is combinations):
P table 1+i.12
┌──┬─────────────────────────────────────────────────────────────┐
│P │1 2 3 4 5 6 7 8 9 10 11 12│
├──┼─────────────────────────────────────────────────────────────┤
│ 1│1 2 6 24 120 720 5040 40320 362880 3628800 39916800 479001600│
│ 2│0 1 3 12 60 360 2520 20160 181440 1814400 19958400 239500800│
│ 3│0 0 1 4 20 120 840 6720 60480 604800 6652800 79833600│
│ 4│0 0 0 1 5 30 210 1680 15120 151200 1663200 19958400│
│ 5│0 0 0 0 1 6 42 336 3024 30240 332640 3991680│
│ 6│0 0 0 0 0 1 7 56 504 5040 55440 665280│
│ 7│0 0 0 0 0 0 1 8 72 720 7920 95040│
│ 8│0 0 0 0 0 0 0 1 9 90 990 11880│
│ 9│0 0 0 0 0 0 0 0 1 10 110 1320│
│10│0 0 0 0 0 0 0 0 0 1 11 132│
│11│0 0 0 0 0 0 0 0 0 0 1 12│
│12│0 0 0 0 0 0 0 0 0 0 0 1│
└──┴─────────────────────────────────────────────────────────────┘
C table 10+10*i.6x
┌──┬─────────────────────────────────────────────────────────────────┐
│C │10 20 30 40 50 60│
├──┼─────────────────────────────────────────────────────────────────┤
│10│ 1 184756 30045015 847660528 10272278170 75394027566│
│20│ 0 1 30045015 137846528820 47129212243960 4191844505805495│
│30│ 0 0 1 847660528 47129212243960 118264581564861424│
│40│ 0 0 0 1 10272278170 4191844505805495│
│50│ 0 0 0 0 1 75394027566│
│60│ 0 0 0 0 0 1│
└──┴─────────────────────────────────────────────────────────────────┘
5 P 100
7.77718e155
100 P 200
8.45055e216
300 P 400
2.09224e254
700 P 800
3.18349e287
5 C 100
75287520
100 C 200
9.05485e58
300 C 400
2.24185e96
700 C 800
3.41114e129
Java
The second part of this task implies that the computations are performed in floating point arithmetic. However, the maximum value of a double in Java is 1.7976931348623157E308. Hence, larger computations would overflow. As a result, this task was interpreted so that “using” means “displayed”.
import java.math.BigInteger;
public class CombinationsAndPermutations {
public static void main(String[] args) {
System.out.println(Double.MAX_VALUE);
System.out.println("A sample of permutations from 1 to 12 with exact Integer arithmetic:");
for ( int n = 1 ; n <= 12 ; n++ ) {
int k = n / 2;
System.out.printf("%d P %d = %s%n", n, k, permutation(n, k));
}
System.out.println();
System.out.println("A sample of combinations from 10 to 60 with exact Integer arithmetic:");
for ( int n = 10 ; n <= 60 ; n += 5 ) {
int k = n / 2;
System.out.printf("%d C %d = %s%n", n, k, combination(n, k));
}
System.out.println();
System.out.println("A sample of permutations from 5 to 15000 displayed in floating point arithmetic:");
System.out.printf("%d P %d = %s%n", 5, 2, display(permutation(5, 2), 50));
for ( int n = 1000 ; n <= 15000 ; n += 1000 ) {
int k = n / 2;
System.out.printf("%d P %d = %s%n", n, k, display(permutation(n, k), 50));
}
System.out.println();
System.out.println("A sample of combinations from 100 to 1000 displayed in floating point arithmetic:");
for ( int n = 100 ; n <= 1000 ; n += 100 ) {
int k = n / 2;
System.out.printf("%d C %d = %s%n", n, k, display(combination(n, k), 50));
}
}
private static String display(BigInteger val, int precision) {
String s = val.toString();
precision = Math.min(precision, s.length());
StringBuilder sb = new StringBuilder();
sb.append(s.substring(0, 1));
sb.append(".");
sb.append(s.substring(1, precision));
sb.append(" * 10^");
sb.append(s.length()-1);
return sb.toString();
}
public static BigInteger combination(int n, int k) {
// Select value with smallest intermediate results
// combination(n, k) = combination(n, n-k)
if ( n-k < k ) {
k = n-k;
}
BigInteger result = permutation(n, k);
while ( k > 0 ) {
result = result.divide(BigInteger.valueOf(k));
k--;
}
return result;
}
public static BigInteger permutation(int n, int k) {
BigInteger result = BigInteger.ONE;
for ( int i = n ; i >= n-k+1 ; i-- ) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
}
- Output:
1.7976931348623157E308 A sample of permutations from 1 to 12 with exact Integer arithmetic: 1 P 0 = 1 2 P 1 = 2 3 P 1 = 3 4 P 2 = 12 5 P 2 = 20 6 P 3 = 120 7 P 3 = 210 8 P 4 = 1680 9 P 4 = 3024 10 P 5 = 30240 11 P 5 = 55440 12 P 6 = 665280 A sample of combinations from 10 to 60 with exact Integer arithmetic: 10 C 5 = 252 15 C 7 = 6435 20 C 10 = 184756 25 C 12 = 5200300 30 C 15 = 155117520 35 C 17 = 4537567650 40 C 20 = 137846528820 45 C 22 = 4116715363800 50 C 25 = 126410606437752 55 C 27 = 3824345300380220 60 C 30 = 118264581564861424 A sample of permutations from 5 to 15000 displayed in floating point arithmetic: 5 P 2 = 2.0 * 10^1 1000 P 500 = 3.2978863640988537122024252070116261706996485697981 * 10^1433 2000 P 1000 = 8.2415012140674255266380217928953202425839550211348 * 10^3167 3000 P 1500 = 8.6229457673788561572282325050469704818001698192368 * 10^5015 4000 P 2000 = 5.5146268042637929575202252487087217092097210095831 * 10^6937 5000 P 2500 = 2.5959899179479570425022364594725223975158226787173 * 10^8914 6000 P 3000 = 6.4684674799045492726351265543133876130483115297807 * 10^10934 7000 P 3500 = 3.6978393541988590953223392044469547113117500019066 * 10^12991 8000 P 4000 = 2.8347416494109128583587900207169062803923698647730 * 10^15079 9000 P 4500 = 3.5613559022062915735922606191272180393638776777367 * 10^17194 10000 P 5000 = 6.7310091721588924046678115055013992269082753633190 * 10^19333 11000 P 5500 = 7.1714299723894354619599359891785521535675525394493 * 10^21494 12000 P 6000 = 4.4778633072110971517945389774618813158941392935141 * 10^23675 13000 P 6500 = 3.6571405647713639990172807053439865891697112165983 * 10^25874 14000 P 7000 = 1.5680448683572888099973548116924953997328821172933 * 10^28090 15000 P 7500 = 2.2454775022523692436484435950526532351441855443096 * 10^30321 A sample of combinations from 100 to 1000 displayed in floating point arithmetic: 100 C 50 = 1.00891344545564193334812497256 * 10^29 200 C 100 = 9.0548514656103281165404177077484163874504589675413 * 10^58 300 C 150 = 9.3759702772827452793193754439064084879232655700081 * 10^88 400 C 200 = 1.0295250013541443297297588032040198675721092538107 * 10^119 500 C 250 = 1.1674431578827768292093473476217661965923008118031 * 10^149 600 C 300 = 1.3510794199619426851447487797850453039723394544919 * 10^179 700 C 350 = 1.5857433585316795487607022764754299250587342835720 * 10^209 800 C 400 = 1.8804244186835312700958607615195351332156581822914 * 10^239 900 C 450 = 2.2474718820660159573188913903771345843514101350359 * 10^269 1000 C 500 = 2.7028824094543656951561469362597527549615200844654 * 10^299
jq
The C implementation of jq approximates large integers by IEEE 754 64-bit floats, and only supports tgamma (true gamma), and thus beyond about 1e308 all accuracy is lost.
On the other hand, gojq, the Go implementation, supports unbounded-precision integer arithmetic, and the `permutation` and `combination` functions below are implemented so as to preserve precision.
def permutation(k): . as $n
| reduce range($n-k+1; 1+$n) as $i (1; . * $i);
def combination(k): . as $n
| if k > ($n/2) then combination($n-k)
else reduce range(0; k) as $i (1; (. * ($n - $i)) / ($i + 1))
end;
# natural log of n!
def log_factorial: (1+.) | tgamma | log;
def log_permutation(k):
(log_factorial - ((.-k) | log_factorial));
def log_combination(k):
(log_factorial - ((. - k)|log_factorial) - (k|log_factorial));
def big_permutation(k): log_permutation(k) | exp;
def big_combination(k): log_combination(k) | exp;
Examples using the C implementation:
12 | permutation(9) #=> 79833600 12 | big_permutation(9) #=> 79833599.99999964 60 | combination(53) #=> 386206920 60 | big_combination(53) #=> 386206920.0000046 145 | big_permutation(133) #=> 1.6801459655817956e+243 170 | big_permutation(133) #=> 5.272846415658284e+263
Examples using gojq, the Go implementation
60 | combinations(30) #=> 118264581564861424 1000 | combination(333) | tostring | "\(.[:40]) ... (\(length) digits in all)" #=> 5776134553147651669777486323549601722339 ... (275 digits in all)
Julia
Infix operators are interpreted by Julia's parser, and (to my knowledge) it isn't possible to define arbitrary characters as such operators. However one can define Unicode "Symbol, Math" characters as infix operators. This solution uses ⊞ for combinations and ⊠ for permutations. An alternative to using the FloatingPoint versions of these operators for large numbers would be to use arbitrary precision integers, BigInt.
Functions
function Base.binomial{T<:FloatingPoint}(n::T, k::T)
exp(lfact(n) - lfact(n - k) - lfact(k))
end
function Base.factorial{T<:FloatingPoint}(n::T, k::T)
exp(lfact(n) - lfact(k))
end
⊞{T<:Real}(n::T, k::T) = binomial(n, k)
⊠{T<:Real}(n::T, k::T) = factorial(n, n-k)
Main
function picknk{T<:Integer}(lo::T, hi::T)
n = rand(lo:hi)
k = rand(1:n)
return (n, k)
end
nsamp = 10
print("Tests of the combinations (⊞) and permutations (⊠) operators for ")
println("integer values.")
println()
lo, hi = 1, 12
print(nsamp, " samples of n ⊠ k with n in [", lo, ", ", hi, "] ")
println("and k in [1, n].")
for i in 1:nsamp
(n, k) = picknk(lo, hi)
println(@sprintf " %2d ⊠ %2d = %18d" n k n ⊠ k)
end
lo, hi = 10, 60
println()
print(nsamp, " samples of n ⊞ k with n in [", lo, ", ", hi, "] ")
println("and k in [1, n].")
for i in 1:nsamp
(n, k) = picknk(lo, hi)
println(@sprintf " %2d ⊞ %2d = %18d" n k n ⊞ k)
end
println()
print("Tests of the combinations (⊞) and permutations (⊠) operators for ")
println("(big) float values.")
println()
lo, hi = 5, 15000
print(nsamp, " samples of n ⊠ k with n in [", lo, ", ", hi, "] ")
println("and k in [1, n].")
for i in 1:nsamp
(n, k) = picknk(lo, hi)
n = BigFloat(n)
k = BigFloat(k)
println(@sprintf " %7.1f ⊠ %7.1f = %10.6e" n k n ⊠ k)
end
lo, hi = 100, 1000
println()
print(nsamp, " samples of n ⊞ k with n in [", lo, ", ", hi, "] ")
println("and k in [1, n].")
for i in 1:nsamp
(n, k) = picknk(lo, hi)
n = BigFloat(n)
k = BigFloat(k)
println(@sprintf " %7.1f ⊞ %7.1f = %10.6e" n k n ⊞ k)
end
- Output:
Tests of the combinations (⊞) and permutations (⊠) operators for integer values. 10 samples of n ⊠ k with n in [1, 12] and k in [1, n]. 4 ⊠ 2 = 12 9 ⊠ 2 = 72 2 ⊠ 1 = 2 8 ⊠ 2 = 56 7 ⊠ 5 = 2520 4 ⊠ 2 = 12 9 ⊠ 8 = 362880 11 ⊠ 6 = 332640 1 ⊠ 1 = 1 8 ⊠ 5 = 6720 10 samples of n ⊞ k with n in [10, 60] and k in [1, n]. 58 ⊞ 26 = 22150361247847371 22 ⊞ 21 = 22 32 ⊞ 30 = 496 11 ⊞ 4 = 330 32 ⊞ 29 = 4960 16 ⊞ 7 = 11440 31 ⊞ 25 = 736281 13 ⊞ 13 = 1 43 ⊞ 28 = 151532656696 49 ⊞ 37 = 92263734836 Tests of the combinations (⊞) and permutations (⊠) operators for (big) float values. 10 samples of n ⊠ k with n in [5, 15000] and k in [1, n]. 8375.0 ⊠ 5578.0 = 2.200496e+20792 1556.0 ⊠ 592.0 = 1.313059e+1833 1234.0 ⊠ 910.0 = 2.231762e+2606 12531.0 ⊠ 9361.0 = 2.339542e+36188 12418.0 ⊠ 6119.0 = 1.049662e+24251 9435.0 ⊠ 8960.0 = 4.273644e+32339 9430.0 ⊠ 5385.0 = 1.471741e+20551 9876.0 ⊠ 5386.0 = 9.073417e+20712 941.0 ⊠ 911.0 = 8.689430e+2358 8145.0 ⊠ 4357.0 = 1.368129e+16407 10 samples of n ⊞ k with n in [100, 1000] and k in [1, n]. 757.0 ⊞ 237.0 = 6.813837e+202 457.0 ⊞ 413.0 = 4.816707e+61 493.0 ⊞ 372.0 = 8.607443e+117 206.0 ⊞ 26.0 = 6.911828e+32 432.0 ⊞ 300.0 = 1.248351e+114 650.0 ⊞ 469.0 = 3.284854e+165 203.0 ⊞ 115.0 = 1.198089e+59 583.0 ⊞ 429.0 = 5.700279e+144 329.0 ⊞ 34.0 = 2.225630e+46 464.0 ⊞ 178.0 = 5.615925e+132
Kotlin
As Kotlin/JVM can use the java.math.BigInteger class, there is no need to use floating point approximations and so we use exact integer arithmetic for all parts of the task.
// version 1.1.2
import java.math.BigInteger
fun perm(n: Int, k: Int): BigInteger {
require(n > 0 && k >= 0)
return (n - k + 1 .. n).fold(BigInteger.ONE) { acc, i -> acc * BigInteger.valueOf(i.toLong()) }
}
fun comb(n: Int, k: Int): BigInteger {
require(n > 0 && k >= 0)
val fact = (2..k).fold(BigInteger.ONE) { acc, i -> acc * BigInteger.valueOf(i.toLong()) }
return perm(n, k) / fact
}
fun main(args: Array<String>) {
println("A sample of permutations from 1 to 12:")
for (n in 1..12) System.out.printf("%2d P %-2d = %d\n", n, n / 3, perm(n, n / 3))
println("\nA sample of combinations from 10 to 60:")
for (n in 10..60 step 10) System.out.printf("%2d C %-2d = %d\n", n, n / 3, comb(n, n / 3))
println("\nA sample of permutations from 5 to 15000:")
val na = intArrayOf(5, 50, 500, 1000, 5000, 15000)
for (n in na) {
val k = n / 3
val s = perm(n, k).toString()
val l = s.length
val e = if (l <= 40) "" else "... (${l - 40} more digits)"
System.out.printf("%5d P %-4d = %s%s\n", n, k, s.take(40), e)
}
println("\nA sample of combinations from 100 to 1000:")
for (n in 100..1000 step 100) {
val k = n / 3
val s = comb(n, k).toString()
val l = s.length
val e = if (l <= 40) "" else "... (${l - 40} more digits)"
System.out.printf("%4d C %-3d = %s%s\n", n, k, s.take(40), e)
}
}
- Output:
A sample of permutations from 1 to 12: 1 P 0 = 1 2 P 0 = 1 3 P 1 = 3 4 P 1 = 4 5 P 1 = 5 6 P 2 = 30 7 P 2 = 42 8 P 2 = 56 9 P 3 = 504 10 P 3 = 720 11 P 3 = 990 12 P 4 = 11880 A sample of combinations from 10 to 60: 10 C 3 = 120 20 C 6 = 38760 30 C 10 = 30045015 40 C 13 = 12033222880 50 C 16 = 4923689695575 60 C 20 = 4191844505805495 A sample of permutations from 5 to 15000: 5 P 1 = 5 50 P 16 = 103017324974226408345600000 500 P 166 = 3534874921742942787609361826601762306844... (395 more digits) 1000 P 333 = 5969326288503415089039701765900784280998... (932 more digits) 5000 P 1666 = 6856745757255674275484536940248896062234... (5986 more digits) 15000 P 5000 = 9649853988727493922014858805931295980792... (20430 more digits) A sample of combinations from 100 to 1000: 100 C 33 = 294692427022540894366527900 200 C 66 = 7269752545169278341527066651192738976755... (14 more digits) 300 C 100 = 4158251463258564744783383526326405580280... (42 more digits) 400 C 133 = 1257948684182108702133348475651965004491... (70 more digits) 500 C 166 = 3926028386194422755220408345072331428197... (97 more digits) 600 C 200 = 2506017783221402805005616770513228835202... (125 more digits) 700 C 233 = 8103203563339599904740453644031138232944... (152 more digits) 800 C 266 = 2645623362683627034288829299556124255091... (180 more digits) 900 C 300 = 1743356373296446642960730765085718347630... (208 more digits) 1000 C 333 = 5776134553147651669777486323549601722339... (235 more digits)
Lua
-- Helper function to display results in scientific notation corrected
function eshow(x)
local e = math.floor(x / math.log(10))
local exponentiated = math.exp(x - e * math.log(10))
-- Corrected format specifier from %.8Fe%+d to %.8e, and manually constructing the scientific notation if needed
return string.format("%.8e", exponentiated) .. "e" .. tostring(e)
end
-- The rest of the functions remain the same
-- Define the factorial function for permutations
function P(n, k)
local x = 1
for i = n - k + 1, n do
x = x * i
end
return x
end
-- Define the function for big permutations using logarithms
function P_big(n, k)
local x = 0
for i = n - k + 1, n do
x = x + math.log(i)
end
return eshow(x)
end
-- Define the combinations function
function C(n, k)
local x = 1
for i = 1, k do
x = x * (n - i + 1) / i
end
return x
end
-- Define the function for big combinations using logarithms
function C_big(n, k)
local x = 0
for i = 1, k do
x = x + math.log(n - i + 1) - math.log(i)
end
return math.exp(x)
end
-- Function to showcase the calculations
function showoff(text, code, fname, ...)
local n = {...}
print("\nA sample of " .. text .. " from " .. n[1] .. " to " .. n[#n] .. "")
for _, v in ipairs(n) do
local k = math.floor(v / 3)
print(v, fname .. " " .. k .. " = ", code(v, k))
end
end
-- Examples of usage
showoff("Permutations", P, "P", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
showoff("Combinations", C, "C", 10, 20, 30, 40, 50, 60)
showoff("Permutations", P_big, "P", 5, 50, 500, 1000, 5000, 15000)
showoff("Combinations", C_big, "C", 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000)
- Output:
A sample of Permutations from 1 to 12 1 P 0 = 1 2 P 0 = 1 3 P 1 = 3 4 P 1 = 4 5 P 1 = 5 6 P 2 = 30 7 P 2 = 42 8 P 2 = 56 9 P 3 = 504 10 P 3 = 720 11 P 3 = 990 12 P 4 = 11880 A sample of Combinations from 10 to 60 10 C 3 = 120.0 20 C 6 = 38760.0 30 C 10 = 30045015.0 40 C 13 = 12033222880.0 50 C 16 = 4923689695575.0 60 C 20 = 4.1918445058055e+15 A sample of Permutations from 5 to 15000 5 P 1 = 5.00000000e+00e0 50 P 16 = 1.03017325e+00e26 500 P 166 = 3.53487492e+00e434 1000 P 333 = 5.96932629e+00e971 5000 P 1666 = 6.85674576e+00e6025 15000 P 5000 = 9.64985399e+00e20469 A sample of Combinations from 100 to 1000 100 C 33 = 2.9469242702254e+26 200 C 66 = 7.2697525451696e+53 300 C 100 = 4.158251463258e+81 400 C 133 = 1.2579486841822e+109 500 C 166 = 3.9260283861944e+136 600 C 200 = 2.5060177832203e+164 700 C 233 = 8.1032035633383e+191 800 C 266 = 2.6456233626831e+219 900 C 300 = 1.7433563732974e+247 1000 C 333 = 5.776134553149e+274
M2000 Interpreter
Module PermComb {
Form 80, 50
perm=lambda (x,y) ->{
def i,z
z=1
For i=x-y+1 to x :z*=i:next i
=z
}
fact=lambda (x) ->{
def i,z
z=1
For i=2 to x :z*=i:next i
=z
}
comb=lambda (x as decimal, y as decimal) ->{
If y>x then {
=0
} else.if x=y then {
=1
} else {
if x-y<y then y=x-y
def decimal i, z=1, ym
ym=y
For i=x to x-y+1
z*=i
z=z/ym
ym-- : if ym<1 then ym=1@
next i
=round(z,0)
}
}
Document Doc$
WriteLn("-- Permutations - from 1 to 12")
For i=1 to 12
l$="" : For j=1 to i : l$+= format$("P({0},{1})={2} ",i, j,perm(i, j)) :next j
Writetext(l$)
next i
WriteLn("-- Combinations from 10 to 60")
For i=10 to 60 step 10
l$="" : For j=1 to i step i div 5 : l$+= format$("C({0},{1})={2} ",i, j,comb(i, j)) :next j
Writetext(l$)
Next i
WriteLn("-- Permutations from 5000 to 15000")
For i=5000 to 15000 step 5000
l$="" : For j=10 to 70 step 20: l$+= format$("P({0},{1})={2} ",i, j,perm(i, j)) :next j
Writetext(l$)
Next i
WriteLn("-- Combinations from 200 to 1000")
For i=200 to 1000 step 200
l$="" : For j=20 to 100 step 20: l$+= format$("C({0},{1})={2} ",i, j,comb(i, j)) :next j
Writetext(l$)
Next i
ClipBoard Doc$
Sub WriteText(a$)
doc$=a$+{
}
Report a$
End Sub
Sub WriteLn(a$)
doc$=a$+{
}
Print a$
End Sub
}
PermComb
- Output:
-- Permutations - from 1 to 12
P(1,1)=1 P(2,1)=2 P(2,2)=2 P(3,1)=3 P(3,2)=6 P(3,3)=6 P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600
-- Combinations from 10 to 60
C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 C(60,1)=60 C(60,13)=5166863427600 C(60,25)=51915437974328292 C(60,37)=23385332420868600 C(60,49)=342700125300
-- Permutations from 5000 to 15000
P(5000,10)=9,67807348145655E+36 P(5000,30)=8,53575581200676E+110 P(5000,50)=6,94616656703754E+184 P(5000,70)=5,21383580146195E+258 P(10000,10)=9,95508690556325E+39 P(10000,30)=9,57391540294832E+119 P(10000,50)=8,84526658067387E+199 P(10000,70)=7,850079552152E+279 P(15000,10)=5,74922667554068E+41 P(15000,30)=1,86266591363916E+125 P(15000,50)=5,87565776023335E+208 P(15000,70)=1,80450662858719E+292
-- Combinations from 200 to 1000
C(200,20)=1613587787967350073386147640 C(200,40)=721126811024990370 C(200,60)=286107190317772000463240955 C(200,80)=900482 C(200,100)=478205104 C(400,20)=3558235073 C(400,40)=130321 C(400,60)=74780600187861332802765 C(400,80)=9521248771125 C(400,100)=447355513982663594791392 C(600,20)=2801445153584 C(600,40)=266319106596345 C(600,60)=14409368913 C(600,80)=271441 C(600,100)=52868467287780595308 C(800,20)=1925279023672620 C(800,40)=23121069591511231041 C(800,60)=18702067923763447158 C(800,80)=1193559552292625 C(800,100)=172727802 C(1000,20)=1239329180287869852 C(1000,40)=1937726921514640866484017 C(1000,60)=149470629867337347460963500 C(1000,80)=1269150275532146867313740 C(1000,100)=10088410532027029794548
Maple
comb := proc (n::integer, k::integer)
return factorial(n)/(factorial(k)*factorial(n-k));
end proc;
perm := proc (n::integer, k::integer)
return factorial(n)/factorial(n-k);
end proc;
Mathematica / Wolfram Language
ClearAll[Combination,Permutation]
Combination[n_,k_]:=Binomial[n,k]
Permutation[n_,k_]:=Binomial[n,k]k!
TableForm[Array[Permutation,{12,12}],TableHeadings->{Range[12],Range[12]}]
TableForm[Array[Combination,{6,6},{{10,60},{10,60}}],TableHeadings->{Range[10,60,10],Range[10,60,10]}]
{Row[{#,"P",#-2}," "],N@Permutation[#,#-2]}&/@{5,1000,5000,10000,15000}//Grid
{Row[{#,"C",#/2}," "],N@Combination[#,#/2]}&/@Range[100,1000,100]//Grid
- Output:
1 2 3 4 5 6 7 8 9 10 11 12 1 1 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 3 3 6 6 0 0 0 0 0 0 0 0 0 4 4 12 24 24 0 0 0 0 0 0 0 0 5 5 20 60 120 120 0 0 0 0 0 0 0 6 6 30 120 360 720 720 0 0 0 0 0 0 7 7 42 210 840 2520 5040 5040 0 0 0 0 0 8 8 56 336 1680 6720 20160 40320 40320 0 0 0 0 9 9 72 504 3024 15120 60480 181440 362880 362880 0 0 0 10 10 90 720 5040 30240 151200 604800 1814400 3628800 3628800 0 0 11 11 110 990 7920 55440 332640 1663200 6652800 19958400 39916800 39916800 0 12 12 132 1320 11880 95040 665280 3991680 19958400 79833600 239500800 479001600 479001600 10 20 30 40 50 60 10 1 0 0 0 0 0 20 184756 1 0 0 0 0 30 30045015 30045015 1 0 0 0 40 847660528 137846528820 847660528 1 0 0 50 10272278170 47129212243960 47129212243960 10272278170 1 0 60 75394027566 4191844505805495 118264581564861424 4191844505805495 75394027566 1 5 P 3 60. 1000 P 998 2.011936300385469*10^2567 5000 P 4998 2.114288963302772*10^16325 10000 P 9998 1.423129840458527*10^35659 15000 P 14998 1.373299516742584*10^56129 100 C 50 1.00891*10^29 200 C 100 9.05485*10^58 300 C 150 9.37597*10^88 400 C 200 1.02953*10^119 500 C 250 1.16744*10^149 600 C 300 1.35108*10^179 700 C 350 1.58574*10^209 800 C 400 1.88042*10^239 900 C 450 2.24747*10^269 1000 C 500 2.70288*10^299
Note that Mathematica can easily handle very big numbers with exact integer arithmetic:
Permutation[200000, 100000]
- Output:
The output is 516777 digits longs:
50287180689616781338617355322585606........0321815299686400000000000000000000......(lots of zeroes)
МК-61/52
П2 <-> П1 -> <-> П7 КПП7 С/П
ИП1 ИП2 - ПП 53 П3 ИП1 ПП 53 ИП3 / В/О
1 ИП1 * L2 21 В/О
ИП1 ИП2 - ПП 53 П3 ИП2 ПП 53 ИП3 * П3 ИП1 ПП 53 ИП3 / В/О
ИП1 ИП2 + 1 - П1 ПП 26 В/О
ВП П0 1 ИП0 * L0 56 В/О
Input: x ^ n ^ k В/О С/П, where x = 8 for permutations; 20 for permutations with repetitions; 26 for combinations; 44 for combinations with repetitions.
Printing of test cases is performed incrementally, which is associated with the characteristics of the device output.
Nim
import bigints
proc perm(n, k: int32): BigInt =
result = initBigInt 1
var
k = n - k
n = n
while n > k:
result *= n
dec n
proc comb(n, k: int32): BigInt =
result = perm(n, k)
var k = k
while k > 0:
result = result div k
dec k
echo "P(1000, 969) = ", perm(1000, 969)
echo "C(1000, 969) = ", comb(1000, 969)
PARI/GP
sample(f,a,b)=for(i=1,4, my(n1=random(b-a)+a,n2=random(b-a)+a); [n1,n2]=[max(n1,n2),min(n1,n2)]; print(n1", "n2": "f(n1,n2)))
permExact(m,n)=factorback([m-n+1..m]);
combExact=binomial;
permApprox(m,n)=exp(lngamma(m+1)-lngamma(m-n+1));
combApprox(m,n)=exp(lngamma(m+1)-lngamma(n+1)-lngamma(m-n+1));
sample(permExact, 1, 12);
sample(combExact, 10, 60);
sample(permApprox, 5, 15000);
sample(combApprox, 100, 1000);
- Output:
?sample(permExact, 1, 12); 8, 2: 56 11, 8: 6652800 9, 9: 362880 6, 1: 6 ?sample(combExact, 10, 60); 46, 14: 239877544005 34, 22: 548354040 51, 20: 77535155627160 49, 26: 58343356817424 ?sample(permApprox, 5, 15000); 8374, 8306: 6.6786635386843773562533982329356314192 E29119 4064, 2497: 7.7325589445068984950461595444827041944 E8575 13234, 784: 1.3439405881429921844444755481930625437 E3221 14136, 1523: 9.7219281356264565060667995087812528666 E6283 ?sample(combApprox, 100, 1000); 988, 702: 4.1430346142101709187524161097370204275 E256 861, 225: 1.9423942269910057792279495652023745087 E213 580, 350: 4.9721729266474994835623000459244303642 E167 977, 846: 6.0586575447000334467351859308510379521 E165
Perl
Although Perl can handle arbitrarily large numbers using Math::BigInt and Math::BigFloat, it's native integers and floats are limited to what the computer's native types can handle.
As with the Raku code, some special handling was done for those values which would have overflowed the native floating point type.
use strict;
use warnings;
showoff( "Permutations", \&P, "P", 1 .. 12 );
showoff( "Combinations", \&C, "C", map $_*10, 1..6 );
showoff( "Permutations", \&P_big, "P", 5, 50, 500, 1000, 5000, 15000 );
showoff( "Combinations", \&C_big, "C", map $_*100, 1..10 );
sub showoff {
my ($text, $code, $fname, @n) = @_;
print "\nA sample of $text from $n[0] to $n[-1]\n";
for my $n ( @n ) {
my $k = int( $n / 3 );
print $n, " $fname $k = ", $code->($n, $k), "\n";
}
}
sub P {
my ($n, $k) = @_;
my $x = 1;
$x *= $_ for $n - $k + 1 .. $n ;
$x;
}
sub P_big {
my ($n, $k) = @_;
my $x = 0;
$x += log($_) for $n - $k + 1 .. $n ;
eshow($x);
}
sub C {
my ($n, $k) = @_;
my $x = 1;
$x *= ($n - $_ + 1) / $_ for 1 .. $k;
$x;
}
sub C_big {
my ($n, $k) = @_;
my $x = 0;
$x += log($n - $_ + 1) - log($_) for 1 .. $k;
exp($x);
}
sub eshow {
my ($x) = @_;
my $e = int( $x / log(10) );
sprintf "%.8Fe%+d", exp($x - $e * log(10)), $e;
}
- Output:
A sample of Permutations from 1 to 12 1 P 0 = 1 2 P 0 = 1 3 P 1 = 3 4 P 1 = 4 5 P 1 = 5 6 P 2 = 30 7 P 2 = 42 8 P 2 = 56 9 P 3 = 504 10 P 3 = 720 11 P 3 = 990 12 P 4 = 11880 A sample of Combinations from 10 to 60 10 C 3 = 120 20 C 6 = 38760 30 C 10 = 30045015 40 C 13 = 12033222880 50 C 16 = 4923689695575 60 C 20 = 4.1918445058055e+15 A sample of Permutations from 5 to 15000 5 P 1 = 5.00000000e+0 50 P 16 = 1.03017325e+26 500 P 166 = 3.53487492e+434 1000 P 333 = 5.96932629e+971 5000 P 1666 = 6.85674576e+6025 15000 P 5000 = 9.64985399e+20469 A sample of Combinations from 100 to 1000 100 C 33 = 2.94692427022544e+26 200 C 66 = 7.26975254516929e+53 300 C 100 = 4.15825146325788e+81 400 C 133 = 1.25794868418216e+109 500 C 166 = 3.92602838619369e+136 600 C 200 = 2.50601778322159e+164 700 C 233 = 8.10320356333741e+191 800 C 266 = 2.64562336268385e+219 900 C 300 = 1.74335637329697e+247 1000 C 333 = 5.77613455314442e+274
Phix
Translation of Raku/Sidef, same results
Update: there are now builtin routines k_perm(n,k) and choose(n,k), slightly more efficient equivalents of P() and C() respectively.
with javascript_semantics function P(integer n,k) return factorial(n)/factorial(n-k) end function function C(integer n,k) return P(n,k)/factorial(k) end function function lstirling(atom n) if n<10 then return lstirling(n+1)-log(n+1) end if return 0.5*log(2*PI*n) + n*log(n/E + 1/(12*E*n)) end function function P_approx(integer n, k) return lstirling(n)-lstirling(n-k) end function function C_approx(integer n, k) return lstirling(n)-lstirling(n-k)-lstirling(k) end function function to_s(atom v) integer e = floor(v/log(10)) return sprintf("%.9ge%d",{power(E,v-e*log(10)),e}) end function -- Test code printf(1,"=> Exact results:\n") for n=1 to 12 do integer p = floor(n/3) printf(1,"P(%d,%d) = %d\n",{n,p,P(n,p)}) end for for n=10 to 60 by 10 do integer p = floor(n/3) printf(1,"C(%d,%d) = %d\n",{n,p,C(n,p)}) end for printf(1,"=> Floating point approximations:\n") constant tests = {5, 50, 500, 1000, 5000, 15000} for i=1 to length(tests) do integer n=tests[i], p = floor(n/3) printf(1,"P(%d,%d) = %s\n",{n,p,to_s(P_approx(n,p))}) end for for n=100 to 1000 by 100 do integer p = floor(n/3) printf(1,"C(%d,%d) = %s\n",{n,p,to_s(C_approx(n,p))}) end for
- Output:
=> Exact results: P(1,0) = 1 P(2,0) = 1 P(3,1) = 3 P(4,1) = 4 P(5,1) = 5 P(6,2) = 30 P(7,2) = 42 P(8,2) = 56 P(9,3) = 504 P(10,3) = 720 P(11,3) = 990 P(12,4) = 11880 C(10,3) = 120 C(20,6) = 38760 C(30,10) = 30045014 C(40,13) = 12033222880 C(50,16) = 4923689695575 C(60,20) = 4191844505805496 => Floating point approximations: P(5,1) = 5e0 P(50,16) = 1.03017326e26 P(500,166) = 3.53487492e434 P(1000,333) = 5.96932629e971 P(5000,1666) = 6.85674576e6025 P(15000,5000) = 9.64985399e20469 C(100,33) = 2.94692433e26 C(200,66) = 7.26975256e53 C(300,100) = 4.15825147e81 C(400,133) = 1.25794868e109 C(500,166) = 3.92602839e136 C(600,200) = 2.50601778e164 C(700,233) = 8.10320356e191 C(800,266) = 2.64562336e219 C(900,300) = 1.74335637e247 C(1000,333) = 5.77613455e274
Python
from __future__ import print_function
from scipy.misc import factorial as fact
from scipy.misc import comb
def perm(N, k, exact=0):
return comb(N, k, exact) * fact(k, exact)
exact=True
print('Sample Perms 1..12')
for N in range(1, 13):
k = max(N-2, 1)
print('%iP%i =' % (N, k), perm(N, k, exact), end=', ' if N % 5 else '\n')
print('\n\nSample Combs 10..60')
for N in range(10, 61, 10):
k = N-2
print('%iC%i =' % (N, k), comb(N, k, exact), end=', ' if N % 50 else '\n')
exact=False
print('\n\nSample Perms 5..1500 Using FP approximations')
for N in [5, 15, 150, 1500, 15000]:
k = N-2
print('%iP%i =' % (N, k), perm(N, k, exact))
print('\nSample Combs 100..1000 Using FP approximations')
for N in range(100, 1001, 100):
k = N-2
print('%iC%i =' % (N, k), comb(N, k, exact))
- Output:
Sample Perms 1..12 1P1 = 1, 2P1 = 2, 3P1 = 3, 4P2 = 12, 5P3 = 60 6P4 = 360, 7P5 = 2520, 8P6 = 20160, 9P7 = 181440, 10P8 = 1814400 11P9 = 19958400, 12P10 = 239500800, Sample Combs 10..60 10C8 = 45, 20C18 = 190, 30C28 = 435, 40C38 = 780, 50C48 = 1225 60C58 = 1770, Sample Perms 5..1500 Using FP approximations 5P3 = 60.0 15P13 = 653837184000.0 150P148 = 2.85669197822e+262 1500P1498 = inf 15000P14998 = inf Sample Combs 100..1000 Using FP approximations 100C98 = 4950.0 200C198 = 19900.0 300C298 = 44850.0 400C398 = 79800.0 500C498 = 124750.0 600C598 = 179700.0 700C698 = 244650.0 800C798 = 319600.0 900C898 = 404550.0 1000C998 = 499500.0
R
R has most of this built in. The documentation for choose warns that it only calculates its result directly if k is small. Skimming what appears to be the source code suggests that 29 is the highest "small" k. This means that we can solve both tasks with little more than R's choose.
perm <- function(n, k) choose(n, k) * factorial(k)
print(perm(seq(from = 3, to = 12, by = 3), seq(from = 2, to = 8, by = 2)))
print(choose(seq(from = 10, to = 60, by = 10), seq(from = 3, to = 18, by = 3)))
print(perm(seq(from = 1500, to = 15000, by = 1500), seq(from = 55, to = 100, by = 5)))
print(choose(seq(from = 100, to = 1000, by = 150), seq(from = 70, to = 100, by = 5)))
- Output:
> print(perm(seq(from = 3, to = 12, by = 3), seq(from = 2, to = 8, by = 2))) [1] 6 360 60480 19958400 > print(choose(seq(from = 10, to = 60, by = 10), seq(from = 3, to = 18, by = 3))) [1] 1.200000e+02 3.876000e+04 1.430715e+07 5.586853e+09 2.250830e+12 9.250296e+14 > print(perm(seq(from = 1500, to = 15000, by = 1500), seq(from = 55, to = 100, by = 5))) [1] 1.777313e+174 2.340618e+208 1.807619e+237 1.972900e+264 2.940161e+290 Inf Inf Inf Inf Inf > print(choose(seq(from = 100, to = 1000, by = 150), seq(from = 70, to = 100, by = 5))) [1] 2.937234e+25 1.158870e+65 4.228142e+85 3.202323e+101 1.944760e+115 8.124447e+127 6.385051e+139
We can notice some interesting things about R from this task. Despite being a mathematical programming language:
- R does not have any function like perm built in.
- R does not have big integers by default and will return Inf without warning.
- R's documentation does not tell us exactly when choose's behaviour changes.
Racket
Racket's "math" library has two functions that compute nCk and nPk. They work only on integers, but since Racket supports unlimited integers there is no need for a floating point estimate:
#lang racket
(require math)
(define C binomial)
(define P permutations)
(C 1000 10) ; -> 263409560461970212832400
(P 1000 10) ; -> 955860613004397508326213120000
(I'll spare this page from yet another big listing of samples...)
Raku
(formerly Perl 6) Raku can't compute arbitrary large floating point values, thus we will use logarithms, as is often needed when dealing with combinations. We'll also use a Stirling method to approximate :
Notice that Raku can process arbitrary long integers, though. So it's not clear whether using floating points is useful in this case.
multi P($n, $k) { [*] $n - $k + 1 .. $n }
multi C($n, $k) { P($n, $k) / [*] 1 .. $k }
sub lstirling(\n) {
n < 10 ?? lstirling(n+1) - log(n+1) !!
.5*log(2*pi*n)+ n*log(n/e+1/(12*e*n))
}
role Logarithm {
method gist {
my $e = (self/10.log).Int;
sprintf "%.8fE%+d", exp(self - $e*10.log), $e;
}
}
multi P($n, $k, :$float!) {
(lstirling($n) - lstirling($n -$k))
but Logarithm
}
multi C($n, $k, :$float!) {
(lstirling($n) - lstirling($n -$k) - lstirling($k))
but Logarithm
}
say "Exact results:";
for 1..12 -> $n {
my $p = $n div 3;
say "P($n, $p) = ", P($n, $p);
}
for 10, 20 ... 60 -> $n {
my $p = $n div 3;
say "C($n, $p) = ", C($n, $p);
}
say '';
say "Floating point approximations:";
for 5, 50, 500, 1000, 5000, 15000 -> $n {
my $p = $n div 3;
say "P($n, $p) = ", P($n, $p, :float);
}
for 100, 200 ... 1000 -> $n {
my $p = $n div 3;
say "C($n, $p) = ", C($n, $p, :float);
}
- Output:
Exact results: P(1, 0) = 1 P(2, 0) = 1 P(3, 1) = 3 P(4, 1) = 4 P(5, 1) = 5 P(6, 2) = 30 P(7, 2) = 42 P(8, 2) = 56 P(9, 3) = 504 P(10, 3) = 720 P(11, 3) = 990 P(12, 4) = 11880 C(10, 3) = 120 C(20, 6) = 38760 C(30, 10) = 30045015 C(40, 13) = 12033222880 C(50, 16) = 4923689695575 C(60, 20) = 4191844505805495 Floating point approximations: P(5, 1) = 5.00000000E+0 P(50, 16) = 1.03017326E+26 P(500, 166) = 3.53487492E+434 P(1000, 333) = 5.96932629E+971 P(5000, 1666) = 6.85674576E+6025 P(15000, 5000) = 9.64985399E+20469 C(100, 33) = 2.94692433E+26 C(200, 66) = 7.26975256E+53 C(300, 100) = 4.15825147E+81 C(400, 133) = 1.25794868E+109 C(500, 166) = 3.92602839E+136 C(600, 200) = 2.50601778E+164 C(700, 233) = 8.10320356E+191 C(800, 266) = 2.64562336E+219 C(900, 300) = 1.74335637E+247 C(1000, 333) = 5.77613455E+274
REXX
The hard part of this REXX program was coding the DO loops for the various ranges.
/*REXX program compute and displays a sampling of combinations and permutations. */
numeric digits 100 /*use 100 decimal digits of precision. */
do j=1 for 12; _= /*show all permutations from 1 ──► 12.*/
do k=1 for j /*step through all J permutations. */
_=_ 'P('j","k')='perm(j,k)" " /*add an extra blank between numbers. */
end /*k*/
say strip(_) /*show the permutations horizontally. */
end /*j*/
say /*display a blank line for readability.*/
do j=10 to 60 by 10; _= /*show some combinations 10 ──► 60. */
do k= 1 to j by j%5 /*step through some combinations. */
_=_ 'C('j","k')='comb(j,k)" " /*add an extra blank between numbers. */
end /*k*/
say strip(_) /*show the combinations horizontally. */
end /*j*/
say /*display a blank line for readability.*/
numeric digits 20 /*force floating point for big numbers.*/
do j=5 to 15000 by 1000; _= /*show a few permutations, big numbers.*/
do k=1 to j for 5 by j%10 /*step through some J permutations. */
_=_ 'P('j","k')='perm(j,k)" " /*add an extra blank between numbers. */
end /*k*/
say strip(_) /*show the permutations horizontally. */
end /*j*/
say /*display a blank line for readability.*/
do j=100 to 1000 by 100; _= /*show a few combinations, big numbers.*/
do k= 1 to j by j%5 /*step through some combinations. */
_=_ 'C('j","k')='comb(j,k)" " /*add an extra blank between numbers. */
end /*k*/
say strip(_) /*show the combinations horizontally. */
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
perm: procedure; parse arg x,y; call .combPerm; return _
.combPerm: _=1; do j=x-y+1 to x; _=_*j; end; return _
!: procedure; parse arg x; !=1; do j=2 to x; !=!*j; end; return !
/*──────────────────────────────────────────────────────────────────────────────────────*/
comb: procedure; parse arg x,y /*arguments: X things, Y at-a-time.*/
if y >x then return 0 /*oops-say, an error, too big a chunk.*/
if x =y then return 1 /*X things are the same as chunk size.*/
if x-y <y then y=x - y /*switch things around for speed. */
call .combPerm /*call subroutine to do heavy lifting. */
return _ / !(y) /*just perform one last division. */
output
P(1,1)=1 P(2,1)=2 P(2,2)=2 P(3,1)=3 P(3,2)=6 P(3,3)=6 P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 C(60,1)=60 C(60,13)=5166863427600 C(60,25)=51915437974328292 C(60,37)=23385332420868600 C(60,49)=342700125300 P(5,1)=5 P(5,1)=5 P(5,1)=5 P(5,1)=5 P(5,1)=5 P(1005,1)=1005 P(1005,101)=9.1176524923776877363E+300 P(1005,201)=1.2772738260896333926E+594 P(1005,301)=6.9244021230613662196E+881 P(1005,401)=2.4492580742838357278E+1163 P(2005,1)=2005 P(2005,201)=1.6533543480914610058E+659 P(2005,401)=3.0753126526205309249E+1305 P(2005,601)=7.9852540678709597130E+1940 P(2005,801)=8.0516979630356802995E+2563 P(3005,1)=3005 P(3005,301)=1.1935689764209015622E+1040 P(3005,601)=1.5619600532077469150E+2062 P(3005,901)=1.0291767405881430479E+3068 P(3005,1201)=1.5669988662999668720E+4055 P(4005,1)=4005 P(4005,401)=4.3808609526948101266E+1435 P(4005,801)=2.3060742016678396933E+2848 P(4005,1201)=2.2044072986703009755E+4239 P(4005,1601)=2.8973897505902543204E+5605 P(5005,1)=5005 P(5005,501)=1.4180262672357809801E+1842 P(5005,1001)=2.8239356430641573722E+3656 P(5005,1501)=3.6832518654277810594E+5443 P(5005,2001)=3.9303728189857603162E+7199 P(6005,1)=6005 P(6005,601)=2.4482219222979658097E+2257 P(6005,1201)=1.0247320583108167487E+4482 P(6005,1801)=1.0131515875595211375E+6674 P(6005,2401)=4.8762853043004294329E+8828 P(7005,1)=7005 P(7005,701)=7.6900396347210828241E+2679 P(7005,1401)=1.2659048848290269952E+5322 P(7005,2101)=1.7753130713788487191E+7926 P(7005,2801)=7.2114365718218704695E+10486 P(8005,1)=8005 P(8005,801)=3.9769062582658855959E+3108 P(8005,1601)=4.3272401446508603181E+6174 P(8005,2401)=1.4466844005282015778E+9197 P(8005,3201)=8.3354759867215982278E+12169 P(9005,1)=9005 P(9005,901)=5.6135384805755901099E+3542 P(9005,1801)=1.1194389175552115248E+7038 P(9005,2701)=2.4737530806300682806E+10484 P(9005,3601)=5.6056491332873455398E+13874 P(10005,1)=10005 P(10005,1001)=5.3580936683833889197E+3981 P(10005,2001)=1.3407350644082770778E+7911 P(10005,3001)=1.3407953461588097193E+11786 P(10005,4001)=8.1811569565040010437E+15598 P(11005,1)=11005 P(11005,1101)=1.1340564277915775963E+4425 P(11005,2201)=7.9753039151558717610E+8792 P(11005,3301)=8.0842724022079710248E+13100 P(11005,4401)=2.9749926937463675736E+17340 P(12005,1)=12005 P(12005,1201)=2.1391703159775094656E+4872 P(12005,2401)=3.7994859265471124812E+9682 P(12005,3601)=3.5081603331307865953E+14427 P(12005,4801)=6.9968644993020337359E+19097 P(13005,1)=13005 P(13005,1301)=1.6832659142209713962E+5323 P(13005,2601)=3.1719005022749408296E+10579 P(13005,3901)=1.1206120643200361213E+15765 P(13005,5201)=5.0883658993886790178E+20869 P(14005,1)=14005 P(14005,1401)=2.9074578200382556975E+5777 P(14005,2801)=1.2835011192416517281E+11483 P(14005,4201)=3.8312600202917546343E+17112 P(14005,5601)=8.7456467698123057261E+22654 C(100,1)=100 C(100,21)=2.0418414110621321255E+21 C(100,41)=2.0116440213369968048E+28 C(100,61)=9.0139240300346304925E+27 C(100,81)=1.3234157293921226741E+20 C(200,1)=200 C(200,41)=8.0006165666286406037E+42 C(200,81)=2.4404128184470558197E+57 C(200,121)=1.0891098528606695394E+57 C(200,161)=5.0935602365182339252E+41 C(300,1)=300 C(300,61)=3.5574671252567510894E+64 C(300,121)=3.3878557197772169409E+86 C(300,181)=1.5098730832156289128E+86 C(300,241)=2.2510943427454545270E+63 C(400,1)=400 C(400,81)=1.6703771503944415835E+86 C(400,161)=4.9770797199515347150E+115 C(400,241)=2.2166247162163128334E+115 C(400,321)=1.0537425948749981954E+85 C(500,1)=500 C(500,101)=8.0859177660929770887E+107 C(500,201)=7.5447012685604958486E+144 C(500,301)=3.3587706644089915087E+144 C(500,401)=5.0915068227892187414E+106 C(600,1)=600 C(600,121)=3.9913554739811382543E+129 C(600,241)=1.1667430218545073615E+174 C(600,361)=5.1927067085306791157E+173 C(600,481)=2.5101559893540422495E+128 C(700,1)=700 C(700,141)=1.9971304197729039382E+151 C(700,281)=1.8294137562513979560E+203 C(700,421)=8.1403842518866639077E+202 C(700,561)=1.2548814134936695871E+150 C(800,1)=800 C(800,161)=1.0093242166331589874E+173 C(800,321)=2.8977104736455704539E+232 C(800,481)=1.2892100651978213666E+232 C(800,641)=6.3378002682503352943E+171 C(900,1)=900 C(900,181)=5.1402207737939392620E+194 C(900,361)=4.6256239559539226532E+261 C(900,541)=2.0577328996911473555E+261 C(900,721)=3.2260054093505652100E+193 C(1000,1)=1000 C(1000,201)=2.6336937554862900107E+216 C(1000,401)=7.4293352412781479131E+290 C(1000,601)=3.3046738011675400053E+290 C(1000,801)=1.6522236106515115238E+215
RPL
≪ / LAST ROT * - ≫ 'BMOD' STO ≪ → n k ≪ # 1d n k - 1 + n FOR j j * NEXT ≫ ≫ 'BPERM' STO ≪ → n k ≪ # 1d DUP n k - 1 + n FOR j j * WHILE DUP2 SWAP BMOD # 0d == 3 PICK k R→B ≤ AND REPEAT OVER / SWAP 1 + SWAP END NEXT SWAP DROP ≫ ≫ 'BCOMB' STO
To mitigate risk of data overflow with 64-bits integers, the inner WHILE..REPEAT
loop permanently attempts to divide the current numerator by increasing values of k.
≪ {} 1 11 FOR j 12 j BPERM + NEXT ≫ ≪ {} 10 50 FOR j 60 j BCOMB + 10 STEP ≫
- Output:
2: { # 12d # 132d # 1320d # 11880d # 95040d # 665280d # 3991680d # 19958400d # 79833600d # 239500800d # 479001600d } 1: { # 75394027566d # 4191844505805495d # 118264581564861424d # 4191844505805495d # 75394027566d }
Floating point approximations can be obtained by the built-in commands, provided that the result does not go beyond 1E500:
1000 150 PERM 1000 400 COMB
- Output:
2: 7.67405677335E444 1: 4.96527238625E290
Ruby
Float calculation as Tcl.
include Math
class Integer
def permutation(k)
(self-k+1 .. self).inject( :*)
end
def combination(k)
self.permutation(k) / (1 .. k).inject( :*)
end
def big_permutation(k)
exp( lgamma_plus(self) - lgamma_plus(self -k))
end
def big_combination(k)
exp( lgamma_plus(self) - lgamma_plus(self - k) - lgamma_plus(k))
end
private
def lgamma_plus(n)
lgamma(n+1)[0] #lgamma is the natural log of gamma
end
end
p 12.permutation(9) #=> 79833600
p 12.big_permutation(9) #=> 79833600.00000021
p 60.combination(53) #=> 386206920
p 145.big_permutation(133) #=> 1.6801459655817956e+243
p 900.big_combination(450) #=> 2.247471882064647e+269
p 1000.big_combination(969) #=> 7.602322407770517e+58
p 15000.big_permutation(73) #=> 6.004137561717704e+304
#That's about the maximum of Float:
p 15000.big_permutation(74) #=> Infinity
#Fixnum has no maximum:
p 15000.permutation(74) #=> 896237613852967826239917238565433149353074416025197784301593335243699358040738127950872384197159884905490054194835376498534786047382445592358843238688903318467070575184552953997615178973027752714539513893159815472948987921587671399790410958903188816684444202526779550201576117111844818124800000000000000000000
Ruby's Arrays have a permutation and a combination method which result in (lazy) enumerators. These Enumerators have a "size" method, which returns the size of the enumerator, or nil if it can’t be calculated lazily. (Since Ruby 2.0)
(1..60).to_a.combination(53).size #=> 386206920
Rust
Almost a verbatim port... the logic is retained but I renounce anyway to use `io::stdout()`, `println!()` is enough. I wonder why f64?!
fn perm(n: f64, k: f64) -> f64 {
let mut result: f64 = 1.0;
let mut i: f64 = 0.0;
while i < k {
result *= n - i;
i += 1.0;
}
result
}
fn comb(n: f64, k: f64) -> f64 {
perm(n, k) / perm(k, k)
}
fn main() {
const P: f64 = 12.0;
const C: f64 = 60.0;
let mut j: f64 = 1.0;
let mut k: f64 = 10.0;
while j < P {
println!("P({},{}) = {}", P, j, perm(P, j).floor());
j += 1.0;
}
while k < C {
println!("C({},{}) = {}", C, k, comb(C, k).floor());
k += 10.0;
}
}
- Output:
P(12,1) = 12 P(12,2) = 132 P(12,3) = 1320 P(12,4) = 11880 P(12,5) = 95040 P(12,6) = 665280 P(12,7) = 3991680 P(12,8) = 19958400 P(12,9) = 79833600 P(12,10) = 239500800 P(12,11) = 479001600 C(60,10) = 75394027566 C(60,20) = 4191844505805495 C(60,30) = 118264581564861420 C(60,40) = 4191844505805495 C(60,50) = 75394027566
Scheme
(define (combinations n k)
(do ((i 0 (+ 1 i))
(res 1 (/ (* res (- n i))
(- k i))))
((= i k) res)))
(define (permutations n k)
(do ((i 0 (+ 1 i))
(res 1 (* res (- n i))))
((= i k) res)))
(display "P(4,2) = ") (display (permutations 4 2)) (newline)
(display "P(8,2) = ") (display (permutations 8 2)) (newline)
(display "P(10,8) = ") (display (permutations 10 8)) (newline)
(display "C(10,8) = ") (display (combinations 10 8)) (newline)
(display "C(20,8) = ") (display (combinations 20 8)) (newline)
(display "C(60,58) = ") (display (combinations 60 58)) (newline)
(display "P(1000,10) = ") (display (permutations 1000 10)) (newline)
(display "P(1000,20) = ") (display (permutations 1000 20)) (newline)
(display "P(15000,2) = ") (display (permutations 15000 3)) (newline)
(display "C(1000,10) = ") (display (combinations 1000 10)) (newline)
(display "C(1000,999) = ") (display (combinations 1000 999)) (newline)
(display "C(1000,1000) = ") (display (combinations 1000 1000)) (newline)
(display "C(15000,14998) = ") (display (combinations 15000 14998)) (newline)
- Output:
P(4,2) = 12 P(8,2) = 56 P(10,8) = 1814400 C(10,8) = 45 C(20,8) = 125970 C(60,58) = 1770 P(1000,10) = 955860613004397508326213120000 P(1000,20) = 825928413359200443640727373872992573951185652339949568000000 P(15000,2) = 3374325030000 C(1000,10) = 263409560461970212832400 C(1000,999) = 1000 C(1000,1000) = 1 C(15000,14998) = 112492500
Sidef
func P(n, k) { n! / ((n-k)!) }
func C(n, k) { binomial(n, k) }
class Logarithm(value) {
method to_s {
var e = int(value/10.log)
"%.8fE%+d" % (exp(value - e*10.log), e)
}
}
func lstirling(n) {
n < 10 ? (lstirling(n+1) - log(n+1))
: (0.5*log(2*Num.pi*n) + n*log(n/Num.e + 1/(12*Num.e*n)))
}
func P_approx(n, k) {
Logarithm((lstirling(n) - lstirling(n -k)))
}
func C_approx(n, k) {
Logarithm((lstirling(n) - lstirling(n -k) - lstirling(k)))
}
say "=> Exact results:"
for n (1..12) {
var p = n//3
say "P(#{n}, #{p}) = #{P(n, p)}"
}
for n (10..60 `by` 10) {
var p = n//3
say "C(#{n}, #{p}) = #{C(n, p)}"
}
say '';
say "=> Floating point approximations:"
for n ([5, 50, 500, 1000, 5000, 15000]) {
var p = n//3
say "P(#{n}, #{p}) = #{P_approx(n, p)}"
}
for n (100..1000 `by` 100) {
var p = n//3
say "C(#{n}, #{p}) = #{C_approx(n, p)}"
}
- Output:
=> Exact results: P(1, 0) = 1 P(2, 0) = 1 P(3, 1) = 3 P(4, 1) = 4 P(5, 1) = 5 P(6, 2) = 30 P(7, 2) = 42 P(8, 2) = 56 P(9, 3) = 504 P(10, 3) = 720 P(11, 3) = 990 P(12, 4) = 11880 C(10, 3) = 120 C(20, 6) = 38760 C(30, 10) = 30045015 C(40, 13) = 12033222880 C(50, 16) = 4923689695575 C(60, 20) = 4191844505805495 => Floating point approximations: P(5, 1) = 5.00000000E+0 P(50, 16) = 1.03017326E+26 P(500, 166) = 3.53487492E+434 P(1000, 333) = 5.96932629E+971 P(5000, 1666) = 6.85674576E+6025 P(15000, 5000) = 9.64985399E+20469 C(100, 33) = 2.94692433E+26 C(200, 66) = 7.26975256E+53 C(300, 100) = 4.15825147E+81 C(400, 133) = 1.25794868E+109 C(500, 166) = 3.92602839E+136 C(600, 200) = 2.50601778E+164 C(700, 233) = 8.10320356E+191 C(800, 266) = 2.64562336E+219 C(900, 300) = 1.74335637E+247 C(1000, 333) = 5.77613455E+274
Stata
The comb function is builtin. Here is an implementation, together with perm:
real scalar comb1(n, k) {
return(exp(lnfactorial(n)-lnfactorial(k)-lnfactorial(n-k)))
}
real scalar perm(n, k) {
return(exp(lnfactorial(n)-lnfactorial(n-k)))
}
Swift
Using AttaSwift's BigInt
import BigInt
func permutations(n: Int, k: Int) -> BigInt {
let l = n - k + 1
guard l <= n else {
return 1
}
return (l...n).reduce(BigInt(1), { $0 * BigInt($1) })
}
func combinations(n: Int, k: Int) -> BigInt {
let fact = {() -> BigInt in
guard k > 1 else {
return 1
}
return (2...k).map({ BigInt($0) }).reduce(1, *)
}()
return permutations(n: n, k: k) / fact
}
print("Sample of permutations from 1 to 12")
for i in 1...12 {
print("\(i) P \(i / 3) = \(permutations(n: i, k: i / 3))")
}
print("\nSample of combinations from 10 to 60")
for i in stride(from: 10, through: 60, by: 10) {
print("\(i) C \(i / 3) = \(combinations(n: i, k: i / 3))")
}
print("\nSample of permutations from 5 to 15,000")
for i in [5, 50, 500, 1000, 5000, 15000] {
let k = i / 3
let res = permutations(n: i, k: k).description
let extra = res.count > 40 ? "... (\(res.count - 40) more digits)" : ""
print("\(i) P \(k) = \(res.prefix(40))\(extra)")
}
print("\nSample of combinations from 100 to 1000")
for i in stride(from: 100, through: 1000, by: 100) {
let k = i / 3
let res = combinations(n: i, k: k).description
let extra = res.count > 40 ? "... (\(res.count - 40) more digits)" : ""
print("\(i) C \(k) = \(res.prefix(40))\(extra)")
}
- Output:
Sample of permutations from 1 to 12 1 P 0 = 1 2 P 0 = 1 3 P 1 = 3 4 P 1 = 4 5 P 1 = 5 6 P 2 = 30 7 P 2 = 42 8 P 2 = 56 9 P 3 = 504 10 P 3 = 720 11 P 3 = 990 12 P 4 = 11880 Sample of combinations from 10 to 60 10 C 3 = 120 20 C 6 = 38760 30 C 10 = 30045015 40 C 13 = 12033222880 50 C 16 = 4923689695575 60 C 20 = 4191844505805495 Sample of permutations from 5 to 15,000 5 P 1 = 5 50 P 16 = 103017324974226408345600000 500 P 166 = 3534874921742942787609361826601762306844... (395 more digits) 1000 P 333 = 5969326288503415089039701765900784280998... (932 more digits) 5000 P 1666 = 6856745757255674275484536940248896062234... (5986 more digits) 15000 P 5000 = 9649853988727493922014858805931295980792... (20430 more digits) Sample of combinations from 100 to 1000 100 C 33 = 294692427022540894366527900 200 C 66 = 7269752545169278341527066651192738976755... (14 more digits) 300 C 100 = 4158251463258564744783383526326405580280... (42 more digits) 400 C 133 = 1257948684182108702133348475651965004491... (70 more digits) 500 C 166 = 3926028386194422755220408345072331428197... (97 more digits) 600 C 200 = 2506017783221402805005616770513228835202... (125 more digits) 700 C 233 = 8103203563339599904740453644031138232944... (152 more digits) 800 C 266 = 2645623362683627034288829299556124255091... (180 more digits) 900 C 300 = 1743356373296446642960730765085718347630... (208 more digits) 1000 C 333 = 5776134553147651669777486323549601722339... (235 more digits)
Tcl
Tcl doesn't allow the definition of new infix operators, so we define and as ordinary functions. There are no problems with loss of significance though: Tcl has supported arbitrary precision integer arithmetic since 8.5.
# Exact integer versions
proc tcl::mathfunc::P {n k} {
set t 1
for {set i $n} {$i > $n-$k} {incr i -1} {
set t [expr {$t * $i}]
}
return $t
}
proc tcl::mathfunc::C {n k} {
set t [P $n $k]
for {set i $k} {$i > 1} {incr i -1} {
set t [expr {$t / $i}]
}
return $t
}
# Floating point versions using the Gamma function
package require math
proc tcl::mathfunc::lnGamma n {math::ln_Gamma $n}
proc tcl::mathfunc::fP {n k} {
expr {exp(lnGamma($n+1) - lnGamma($n-$k+1))}
}
proc tcl::mathfunc::fC {n k} {
expr {exp(lnGamma($n+1) - lnGamma($n-$k+1) - lnGamma($k+1))}
}
Demonstrating:
# Using the exact integer versions
puts "A sample of Permutations from 1 to 12:"
for {set i 4} {$i <= 12} {incr i} {
set ii [expr {$i - 2}]
set iii [expr {$i - int(sqrt($i))}]
puts "$i P $ii = [expr {P($i,$ii)}], $i P $iii = [expr {P($i,$iii)}]"
}
puts "A sample of Combinations from 10 to 60:"
for {set i 10} {$i <= 60} {incr i 10} {
set ii [expr {$i - 2}]
set iii [expr {$i - int(sqrt($i))}]
puts "$i C $ii = [expr {C($i,$ii)}], $i C $iii = [expr {C($i,$iii)}]"
}
# Using the approximate floating point versions
puts "A sample of Permutations from 5 to 15000:"
for {set i 5} {$i <= 150} {incr i 10} {
set ii [expr {$i - 2}]
set iii [expr {$i - int(sqrt($i))}]
puts "$i P $ii = [expr {fP($i,$ii)}], $i P $iii = [expr {fP($i,$iii)}]"
}
puts "A sample of Combinations from 100 to 1000:"
for {set i 100} {$i <= 1000} {incr i 100} {
set ii [expr {$i - 2}]
set iii [expr {$i - int(sqrt($i))}]
puts "$i C $ii = [expr {fC($i,$ii)}], $i C $iii = [expr {fC($i,$iii)}]"
}
- Output:
A sample of Permutations from 1 to 12: 4 P 2 = 12, 4 P 2 = 12 5 P 3 = 60, 5 P 3 = 60 6 P 4 = 360, 6 P 4 = 360 7 P 5 = 2520, 7 P 5 = 2520 8 P 6 = 20160, 8 P 6 = 20160 9 P 7 = 181440, 9 P 6 = 60480 10 P 8 = 1814400, 10 P 7 = 604800 11 P 9 = 19958400, 11 P 8 = 6652800 12 P 10 = 239500800, 12 P 9 = 79833600 A sample of Combinations from 10 to 60: 10 C 8 = 45, 10 C 7 = 120 20 C 18 = 190, 20 C 16 = 4845 30 C 28 = 435, 30 C 25 = 142506 40 C 38 = 780, 40 C 34 = 3838380 50 C 48 = 1225, 50 C 43 = 99884400 60 C 58 = 1770, 60 C 53 = 386206920 A sample of Permutations from 5 to 15000: 5 P 3 = 59.9999999964319, 5 P 3 = 59.9999999964319 15 P 13 = 653837183936.7548, 15 P 12 = 217945727984.54794 25 P 23 = 7.755605021026223e+24, 25 P 20 = 1.2926008369145724e+23 35 P 33 = 5.166573982873315e+39, 35 P 30 = 8.610956638634269e+37 45 P 43 = 5.981111043018166e+55, 45 P 39 = 1.6614197342883882e+53 55 P 53 = 6.348201676661335e+72, 55 P 48 = 2.5191276496660396e+69 65 P 63 = 4.123825295988996e+90, 65 P 57 = 2.0455482620718488e+86 75 P 73 = 1.2404570405684596e+109, 75 P 67 = 6.153060717624475e+104 85 P 83 = 1.4085520572027225e+128, 85 P 76 = 7.763183737477006e+122 95 P 93 = 5.164989244208789e+147, 95 P 86 = 2.846665148075141e+142 105 P 103 = 5.406983791334563e+167, 105 P 95 = 2.980039567808848e+161 115 P 113 = 1.462546846791721e+188, 115 P 105 = 8.060774068156828e+181 125 P 123 = 9.413385884788385e+208, 125 P 114 = 4.716503269639238e+201 135 P 133 = 1.345236353714729e+230, 135 P 124 = 6.74020138809567e+222 145 P 143 = 4.0239630289197437e+251, 145 P 133 = 1.6801459658196038e+243 A sample of Combinations from 100 to 1000: 100 C 98 = 4950.000000564707, 100 C 90 = 17310309460118.861 200 C 198 = 19900.000002250566, 200 C 186 = 1.1797916416885855e+21 300 C 298 = 44850.00000506082, 300 C 283 = 2.287708142503998e+27 400 C 398 = 79800.00000901309, 400 C 380 = 2.788360984244711e+33 500 C 498 = 124750.00001405331, 500 C 478 = 1.327364247175741e+38 600 C 598 = 179700.00002031153, 600 C 576 = 4.7916866834178515e+42 700 C 698 = 244650.00002750417, 700 C 674 = 1.454786513417567e+47 800 C 798 = 319600.0000360682, 800 C 772 = 3.933526871778561e+51 900 C 898 = 404550.0000452471, 900 C 870 = 9.803348169192494e+55 1000 C 998 = 499500.0000564987, 1000 C 969 = 7.602322409167201e+58
It should be noted that for large values, it can be much faster to use the floating point version (at a cost of losing significance). In particular expr C(1000,500)
takes approximately 1000 times longer to compute than expr fC(1000,500)
VBScript
' Combinations and permutations - vbs - 10/04/2017
dim i,j
Wscript.StdOut.WriteLine "-- Long Integer - Permutations - from 1 to 12"
for i=1 to 12
for j=1 to i
Wscript.StdOut.Write "P(" & i & "," & j & ")=" & perm(i,j) & " "
next 'j
Wscript.StdOut.WriteLine ""
next 'i
Wscript.StdOut.WriteLine "-- Float integer - Combinations from 10 to 60"
for i=10 to 60 step 10
for j=1 to i step i\5
Wscript.StdOut.Write "C(" & i & "," & j & ")=" & comb(i,j) & " "
next 'j
Wscript.StdOut.WriteLine ""
next 'i
Wscript.StdOut.WriteLine "-- Float integer - Permutations from 5000 to 15000"
for i=5000 to 15000 step 5000
for j=10 to 70 step 20
Wscript.StdOut.Write "C(" & i & "," & j & ")=" & perm(i,j) & " "
next 'j
Wscript.StdOut.WriteLine ""
next 'i
Wscript.StdOut.WriteLine "-- Float integer - Combinations from 200 to 1000"
for i=200 to 1000 step 200
for j=20 to 100 step 20
Wscript.StdOut.Write "P(" & i & "," & j & ")=" & comb(i,j) & " "
next 'j
Wscript.StdOut.WriteLine ""
next 'i
function perm(x,y)
dim i,z
z=1
for i=x-y+1 to x
z=z*i
next 'i
perm=z
end function 'perm
function fact(x)
dim i,z
z=1
for i=2 to x
z=z*i
next 'i
fact=z
end function 'fact
function comb(byval x,byval y)
if y>x then
comb=0
elseif x=y then
comb=1
else
if x-y<y then y=x-y
comb=perm(x,y)/fact(y)
end if
end function 'comb
- Output:
-- Long Integer - Permutations - from 1 to 12 P(1,1)=1 P(2,1)=2 P(2,2)=2 P(3,1)=3 P(3,2)=6 P(3,3)=6 P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 -- Float integer - Combinations from 10 to 60 C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 C(60,1)=60 C(60,13)=5166863427600 C(60,25)=5,19154379743283E+16 C(60,37)=2,33853324208686E+16 C(60,49)=342700125300 -- Float integer - Permutations from 5000 to 15000 C(5000,10)=9,67807348145655E+36 C(5000,30)=8,53575581200676E+110 C(5000,50)=6,94616656703754E+184 C(5000,70)=5,21383580146194E+258 C(10000,10)=9,95508690556325E+39 C(10000,30)=9,57391540294832E+119 C(10000,50)=8,84526658067387E+199 C(10000,70)=7,850079552152E+279 C(15000,10)=5,74922667554068E+41 C(15000,30)=1,86266591363916E+125 C(15000,50)=5,87565776023335E+208 C(15000,70)=1,80450662858719E+292 -- Float integer - Combinations from 200 to 1000 P(200,20)=1,61358778796735E+27 P(200,40)=2,05015799519859E+42 P(200,60)=7,04050484926892E+51 P(200,80)=1,64727865245176E+57 P(200,100)=9,05485146561033E+58 P(400,20)=2,7883609836709E+33 P(400,40)=1,9703374084393E+55 P(400,60)=1,50867447857277E+72 P(400,80)=4,22814216193593E+85 P(400,100)=2,24185479155434E+96 P(600,20)=1,09108668819553E+37 P(600,40)=4,33518929550349E+62 P(600,60)=2,77426667704894E+83 P(600,80)=1,00412999166192E+101 P(600,100)=1,11141121906619E+116 P(800,20)=3,72976760205571E+39 P(800,40)=6,04464684067502E+67 P(800,60)=1,90370080982158E+91 P(800,80)=4,14170924105943E+111 P(800,100)=3,4111376846871E+129 P(1000,20)=3,39482811302458E+41 P(1000,40)=5,55974423571664E+71 P(1000,60)=1,97427486218598E+97 P(1000,80)=5,43269728730706E+119 P(1000,100)=6,38505119263051E+139
Visual Basic .NET
' Combinations and permutations - 10/04/2017
Imports System.Numerics 'BigInteger
Module CombPermRc
Sub Main()
Dim i, j As Long
For i = 1 To 12
For j = 1 To i
Console.Write("P(" & i & "," & j & ")=" & PermBig(i, j).ToString & " ")
Next j
Console.WriteLine("")
Next i
Console.WriteLine("--")
For i = 10 To 60 Step 10
For j = 1 To i Step i \ 5
Console.Write("C(" & i & "," & j & ")=" & CombBig(i, j).ToString & " ")
Next j
Console.WriteLine("")
Next i
Console.WriteLine("--")
For i = 5000 To 15000 Step 5000
For j = 4000 To 5000 Step 1000
Console.Write("P(" & i & "," & j & ")=" & PermBig(i, j).ToString("E") & " ")
Next j
Console.WriteLine("")
Next i
Console.WriteLine("--")
For i = 5000 To 15000 Step 5000
For j = 4000 To 5000 Step 1000
Console.Write("C(" & i & "," & j & ")=" & CombBig(i, j).ToString("E") & " ")
Next j
Console.WriteLine("")
Next i
Console.WriteLine("--")
i = 5000 : j = 4000
Console.WriteLine("C(" & i & "," & j & ")=" & CombBig(i, j).ToString)
End Sub 'Main
Function PermBig(x As Long, y As Long) As BigInteger
Dim i As Long, z As BigInteger
z = 1
For i = x - y + 1 To x
z = z * i
Next i
Return (z)
End Function 'PermBig
Function FactBig(x As Long) As BigInteger
Dim i As Long, z As BigInteger
z = 1
For i = 2 To x
z = z * i
Next i
Return (z)
End Function 'FactBig
Function CombBig(ByVal x As Long, ByVal y As Long) As BigInteger
If y > x Then
Return (0)
ElseIf x = y Then
Return (1)
Else
If x - y < y Then y = x - y
Return (PermBig(x, y) / FactBig(y))
End If
End Function 'CombBig
End Module
- Output:
P(1,1)=1 P(2,1)=2 P(2,2)=2 P(3,1)=3 P(3,2)=6 P(3,3)=6 P(4,1)=4 P(4,2)=12 P(4,3)=24 P(4,4)=24 P(5,1)=5 P(5,2)=20 P(5,3)=60 P(5,4)=120 P(5,5)=120 P(6,1)=6 P(6,2)=30 P(6,3)=120 P(6,4)=360 P(6,5)=720 P(6,6)=720 P(7,1)=7 P(7,2)=42 P(7,3)=210 P(7,4)=840 P(7,5)=2520 P(7,6)=5040 P(7,7)=5040 P(8,1)=8 P(8,2)=56 P(8,3)=336 P(8,4)=1680 P(8,5)=6720 P(8,6)=20160 P(8,7)=40320 P(8,8)=40320 P(9,1)=9 P(9,2)=72 P(9,3)=504 P(9,4)=3024 P(9,5)=15120 P(9,6)=60480 P(9,7)=181440 P(9,8)=362880 P(9,9)=362880 P(10,1)=10 P(10,2)=90 P(10,3)=720 P(10,4)=5040 P(10,5)=30240 P(10,6)=151200 P(10,7)=604800 P(10,8)=1814400 P(10,9)=3628800 P(10,10)=3628800 P(11,1)=11 P(11,2)=110 P(11,3)=990 P(11,4)=7920 P(11,5)=55440 P(11,6)=332640 P(11,7)=1663200 P(11,8)=6652800 P(11,9)=19958400 P(11,10)=39916800 P(11,11)=39916800 P(12,1)=12 P(12,2)=132 P(12,3)=1320 P(12,4)=11880 P(12,5)=95040 P(12,6)=665280 P(12,7)=3991680 P(12,8)=19958400 P(12,9)=79833600 P(12,10)=239500800 P(12,11)=479001600 P(12,12)=479001600 -- C(10,1)=10 C(10,3)=120 C(10,5)=252 C(10,7)=120 C(10,9)=10 C(20,1)=20 C(20,5)=15504 C(20,9)=167960 C(20,13)=77520 C(20,17)=1140 C(30,1)=30 C(30,7)=2035800 C(30,13)=119759850 C(30,19)=54627300 C(30,25)=142506 C(40,1)=40 C(40,9)=273438880 C(40,17)=88732378800 C(40,25)=40225345056 C(40,33)=18643560 C(50,1)=50 C(50,11)=37353738800 C(50,21)=67327446062800 C(50,31)=30405943383200 C(50,41)=2505433700 C(60,1)=60 C(60,13)=5166863427600 C(60,25)=51915437974328292 C(60,37)=23385332420868600 C(60,49)=342700125300 -- P(5000,4000)=1,050873E+13758 P(5000,5000)=4,228578E+16325 P(10000,4000)=1,060455E+15594 P(10000,5000)=6,731009E+19333 P(15000,4000)=8,685001E+16448 P(15000,5000)=9,649854E+20469 -- C(5000,4000)=5,746236E+1084 C(5000,5000)=1,000000E+000 C(10000,4000)=5,798630E+2920 C(10000,5000)=1,591790E+3008 C(15000,4000)=4,749011E+3775 C(15000,5000)=2,282057E+4144 -- C(5000,4000)=57462357505803375604893834658665168251899919793850512934468881710397678593302188064618445132583370701755893065787216750992391223467601994741594656878559929037277303674963658032197224327768110236651567704673226756781828332650887849150208195780031161286578505113618731045004523840401144118298192191997565735245181433457469532981432785237769191864102953974244072964471109551273603780184330987071947790993108191904370472373403157802158903129815170101708451875442019845175637901995588390614304812103202403626211504997668649346891167495657556154392183988627948442807346603688457854135114491955258804187129028256547543888109987151649038111791932035229202856007767332717845596528598314477979861265222941138323298702349967224867703420888363395662988291273283611081068577160905840445308086112429900453394212790633910614322699210850302387512579976209123523546689147207974269396548873838155355768985614160932799226261509866933143702889005270480654844312094564956178277998090168826124850606847021667494019587077659107276117413835912767949017954979839258481340540145909025953956582025656306426226560
Wren
import "./big" for BigInt
import "./fmt" for Fmt
import "./iterate" for Stepped
var perm = Fn.new { |n, k|
if (n <= 0 || k < 0) Fiber.abort("Invalid argument(s).")
if (k == 0) return BigInt.one
return (n-k+1..n).reduce(BigInt.one) { |acc, i| acc * BigInt.new(i) }
}
var comb = Fn.new { |n, k|
if (n <= 0 || k < 0) Fiber.abort("Invalid argument(s).")
var fact = BigInt.one
if (k > 1) fact = (2..k).reduce(BigInt.one) { |acc, i| acc * BigInt.new(i) }
return perm.call(n, k) / fact
}
System.print("A sample of permutations from 1 to 12:")
for (n in 1..12) Fmt.print("$2d P $-2d = $i", n, (n/3).floor, perm.call(n, (n/3).floor))
System.print("\nA sample of combinations from 10 to 60:")
for (n in Stepped.new(10..60, 10)) {
Fmt.print("$2d C $-2d = $i", n, (n/3).floor, comb.call(n, (n/3).floor))
}
System.print("\nA sample of permutations from 5 to 15000:")
var na = [5, 50, 500, 1000, 5000, 15000]
for (n in na) {
var k = (n/3).floor
var s = perm.call(n, k).toString
var l = s.count
var e = (l <= 40) ? "" : "... (%(l - 40) more digits)"
Fmt.print("$5d P $-4d = $s$s", n, k, s.take(40).join(), e)
}
System.print("\nA sample of combinations from 100 to 1000:")
for (n in Stepped.new(100..1000, 100)) {
var k = (n/3).floor
var s = comb.call(n, k).toString
var l = s.count
var e = (l <= 40) ? "" : "... (%(l - 40) more digits)"
Fmt.print("$4d C $-3d = $s$s", n, k, s.take(40).join(), e)
}
- Output:
A sample of permutations from 1 to 12: 1 P 0 = 1 2 P 0 = 1 3 P 1 = 3 4 P 1 = 4 5 P 1 = 5 6 P 2 = 30 7 P 2 = 42 8 P 2 = 56 9 P 3 = 504 10 P 3 = 720 11 P 3 = 990 12 P 4 = 11880 A sample of combinations from 10 to 60: 10 C 3 = 120 20 C 6 = 38760 30 C 10 = 30045015 40 C 13 = 12033222880 50 C 16 = 4923689695575 60 C 20 = 4191844505805495 A sample of permutations from 5 to 15000: 5 P 1 = 5 50 P 16 = 103017324974226408345600000 500 P 166 = 3534874921742942787609361826601762306844... (395 more digits) 1000 P 333 = 5969326288503415089039701765900784280998... (932 more digits) 5000 P 1666 = 6856745757255674275484536940248896062234... (5986 more digits) 15000 P 5000 = 9649853988727493922014858805931295980792... (20430 more digits) A sample of combinations from 100 to 1000: 100 C 33 = 294692427022540894366527900 200 C 66 = 7269752545169278341527066651192738976755... (14 more digits) 300 C 100 = 4158251463258564744783383526326405580280... (42 more digits) 400 C 133 = 1257948684182108702133348475651965004491... (70 more digits) 500 C 166 = 3926028386194422755220408345072331428197... (97 more digits) 600 C 200 = 2506017783221402805005616770513228835202... (125 more digits) 700 C 233 = 8103203563339599904740453644031138232944... (152 more digits) 800 C 266 = 2645623362683627034288829299556124255091... (180 more digits) 900 C 300 = 1743356373296446642960730765085718347630... (208 more digits) 1000 C 333 = 5776134553147651669777486323549601722339... (235 more digits)
zig
const std = @import("std");
const num = f64;
pub fn perm(n: num, k: num) num {
var result: num = 1;
var i: num = 0;
while (i < k) : (i += 1) {
result *= n - i;
}
return result;
}
pub fn comb(n: num, k: num) num {
return perm(n, k) / perm(k, k);
}
pub fn main() !void {
var stdout = std.io.getStdOut().writer();
const p: num = 12;
const c: num = 60;
var j: num = 1;
var k: num = 10;
while (j < p) : (j += 1) {
try stdout.print("P({d},{d}) = {d}\n", .{ p, j, @floor(perm(p, j)) });
}
while (k < c) : (k += 10) {
try stdout.print("C({d},{d}) = {d}\n", .{ c, k, @floor(comb(c, k)) });
}
}
- Output:
P(12,1) = 12 P(12,2) = 132 P(12,3) = 1320 P(12,4) = 11880 P(12,5) = 95040 P(12,6) = 665280 P(12,7) = 3991680 P(12,8) = 19958400 P(12,9) = 79833600 P(12,10) = 239500800 P(12,11) = 479001600 C(60,10) = 75394027566 C(60,20) = 4191844505805495 C(60,30) = 118264581564861420 C(60,40) = 4191844505805495 C(60,50) = 75394027566
- Programming Tasks
- Probability and statistics
- WikipediaSourced
- 11l
- ALGOL 68
- Arturo
- Bracmat
- C
- C sharp
- C++
- Boost
- Common Lisp
- Crystal
- D
- EasyLang
- EchoLisp
- Elixir
- Erlang
- Factor
- FreeBASIC
- Go
- Haskell
- Icon
- Unicon
- J
- Java
- Jq
- Julia
- Kotlin
- Lua
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- МК-61/52
- Nim
- PARI/GP
- Perl
- Phix
- Python
- SciPy
- R
- Racket
- Raku
- REXX
- RPL
- Ruby
- Rust
- Scheme
- Sidef
- Stata
- Swift
- Tcl
- Tcllib
- VBScript
- Visual Basic .NET
- Wren
- Wren-big
- Wren-fmt
- Wren-iterate
- Zig