Combinations and permutations: Difference between revisions

From Rosetta Code
Content added Content deleted
m (tidy up description)
m (→‎[[Combinations_and_permutations#ALGOL 68]]: use a consistent naming convention)
Line 17: Line 17:
'''File: prelude_combinations_and_permutations.a68'''<lang algol68># -*- coding: utf-8 -*- #
'''File: prelude_combinations_and_permutations.a68'''<lang algol68># -*- coding: utf-8 -*- #


COMMENT REQUIRED by "prelude_combinations_and_permutations.a68" CO
CO REQUIRES
MODE CPINT = #LONG# INT;
MODE CPINT = #LONG# ~;
MODE CPOUT = #LONG# INT; # the answer, can be REAL #
MODE CPOUT = #LONG# ~; # the answer, can be REAL #
MODE CPREAL = REAL; # the answer, can be REAL #
MODE CPREAL = ~; # the answer, can be REAL #
MODE CPARGS = STRUCT(CHAR name, #REF# CPINT n,k);
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 37: Line 41:
);
);


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+1)! #
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;
Line 51: Line 59:
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 61: Line 70:
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 70: Line 80:
);
);


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 86: Line 92:
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 underslow here #
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 97: Line 103:
out # EXIT with: n P r OVER r P r #
out # EXIT with: n P r OVER r P r #
);
);
END COMMENT


SKIP</lang>'''File: test_combinations_and_permutations.a68'''<lang algol68>#!/usr/bin/a68g --script #
SKIP</lang>'''File: test_combinations_and_permutations.a68'''<lang algol68>#!/usr/bin/a68g --script #
Line 105: Line 112:
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 111: Line 117:
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 138: Line 147:
OD;
OD;


printf($l"A sample of Combinations from 100 to 1000:"l$);
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 183: Line 192:
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 100 to 1000:
A sample of Combinations from 10 to 190:
(100 C 98) = 4950.0, (100 C 90) = 17310309456440.0
(100 C 98) = 4950.0, (100 C 90) = 17310309456438.8
(200 C 198) = 19900.0, (200 C 186) = 1179791641436990000000.0
(200 C 198) = 19900.0, (200 C 186) = 1179791641436960000000.0
(300 C 298) = 44850.0, (300 C 283) = 2287708142023200000000000000.0
(300 C 298) = 44850.0, (300 C 283) = 2287708142022840000000000000.0
(400 C 398) = 79800.0, (400 C 380) = 2788360983670890000000000000000000.0
(400 C 398) = 79800.0, (400 C 380) = 2788360983670300000000000000000000.0
(500 C 498) = 124750.0, (500 C 478) = 132736424690819000000000000000000000000.0
(500 C 498) = 124750.0, (500 C 478) = 132736424690773000000000000000000000000.0
(600 C 598) = 179700.0, (600 C 576) = 4791686682466570000000000000000000000000000.0
(600 C 598) = 179700.0, (600 C 576) = 4791686682467800000000000000000000000000000.0
(700 C 698) = 244650.0, (700 C 674) = 145478651313634000000000000000000000000000000000.0
(700 C 698) = 244650.0, (700 C 674) = 145478651313640000000000000000000000000000000000.0
(800 C 798) = 319600.0, (800 C 772) = 3933526871034580000000000000000000000000000000000000.0
(800 C 798) = 319600.0, (800 C 772) = 3933526871034430000000000000000000000000000000000000.0
(900 C 898) = 404550.0, (900 C 870) = 98033481673745800000000000000000000000000000000000000000.0
(900 C 898) = 404550.0, (900 C 870) = 98033481673646900000000000000000000000000000000000000000.0
(1000 C 998) = 499500.0, (1000 C 969) = 76023224077694500000000000000000000000000000000000000000000.0
(1000 C 998) = 499500.0, (1000 C 969) = 76023224077705100000000000000000000000000000000000000000000.0
</pre>
</pre>



Revision as of 08:02, 16 April 2013

Combinations and permutations is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Combinations and permutations is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
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)

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:

  • Permutations from 1 to 12 and Combinations from 10 to 60 using exact Integer arithmetic.
  • 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.

ALGOL 68

Works with: ALGOL 68 version Revision 1 - one minor extension to language used - PRAGMA READ, similar to C's #include directive.
Works with: ALGOL 68G version Any - tested with release algol68g-2.6.

File: prelude_combinations_and_permutations.a68<lang algol68># -*- 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: ~;
  1. PROVIDES:#
  2. OP C = (CP~,CP~)CP~: ~ #
  3. 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 #

  1. 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;
  1. basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r+1)! #
 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));
  1. basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r+1)! #

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;
  1. basically nPk = (n-r+1)(n-r+2)...(n-2)(n-1)n = n!/(n-r+1)! #
 CPREAL i := n-r+1;
 WHILE i <= n DO
   out*:= i;
  1. 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

  1. 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 
  1. try and prevent overflow, p.s. there must be a smarter way to do this #
  2. 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));
  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 #
  1. 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</lang>File: test_combinations_and_permutations.a68<lang algol68>#!/usr/bin/a68g --script #

  1. -*- 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 #
 );
  1. PROVIDES:#
  2. OP C = (CP~,CP~)CP~: ~ #
  3. 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</lang>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

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.

Library: Tcllib (Package: math)

<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

}

  1. 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))}

}</lang> Demonstrating: <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)}]"

}

  1. 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)}]"

}</lang>

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)