Mercurial > hg > octave-lyh
annotate scripts/specfun/nchoosek.m @ 14090:281ecc6fb431 stable
nchoosek.m: Update documentation, fix input validation, add more %!tests
* nchoosek.m: Update documentation, fix input validation, add more %!tests
author | Rik <octave@nomad.inbox5.com> |
---|---|
date | Wed, 21 Dec 2011 16:53:43 -0800 |
parents | 5b49cafe0599 |
children | 050bc580cb60 |
rev | line source |
---|---|
11523 | 1 ## Copyright (C) 2001-2011 Rolf Fabian and Paul Kienzle |
8391
343f0fbca6eb
implement nchoosek without recursion
Jaroslav Hajek <highegg@gmail.com>
parents:
8361
diff
changeset
|
2 ## Copyright (C) 2008 Jaroslav Hajek |
5827 | 3 ## |
4 ## This file is part of Octave. | |
5 ## | |
6 ## Octave is free software; you can redistribute it and/or modify it | |
7 ## under the terms of the GNU General Public License as published by | |
7016 | 8 ## the Free Software Foundation; either version 3 of the License, or (at |
9 ## your option) any later version. | |
5827 | 10 ## |
11 ## Octave is distributed in the hope that it will be useful, but | |
12 ## WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 ## General Public License for more details. | |
15 ## | |
16 ## You should have received a copy of the GNU General Public License | |
7016 | 17 ## along with Octave; see the file COPYING. If not, see |
18 ## <http://www.gnu.org/licenses/>. | |
5827 | 19 |
20 ## -*- texinfo -*- | |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
21 ## @deftypefn {Function File} {@var{c} =} nchoosek (@var{n}, @var{k}) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
22 ## @deftypefnx {Function File} {@var{c} =} nchoosek (@var{set}, @var{k}) |
5827 | 23 ## |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
24 ## Compute the binomial coefficient or all combinations of a set of items. |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
25 ## |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
26 ## If @var{n} is a scalar then calculate the binomial coefficient |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
27 ## of @var{n} and @var{k} which is defined as |
5827 | 28 ## @tex |
29 ## $$ | |
30 ## {n \choose k} = {n (n-1) (n-2) \cdots (n-k+1) \over k!} | |
6754 | 31 ## = {n! \over k! (n-k)!} |
5827 | 32 ## $$ |
33 ## @end tex | |
8517
81d6ab3ac93c
Allow documentation tobe built for other formats than tex and info
sh@sh-laptop
parents:
8506
diff
changeset
|
34 ## @ifnottex |
5827 | 35 ## |
36 ## @example | |
37 ## @group | |
38 ## / \ | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
39 ## | n | n (n-1) (n-2) @dots{} (n-k+1) n! |
6754 | 40 ## | | = ------------------------- = --------- |
41 ## | k | k! k! (n-k)! | |
5827 | 42 ## \ / |
43 ## @end group | |
44 ## @end example | |
10821
693e22af08ae
Grammarcheck documentation of m-files
Rik <octave@nomad.inbox5.com>
parents:
10800
diff
changeset
|
45 ## |
8517
81d6ab3ac93c
Allow documentation tobe built for other formats than tex and info
sh@sh-laptop
parents:
8506
diff
changeset
|
46 ## @end ifnottex |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
47 ## @noindent |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
48 ## This is the number of combinations of @var{n} items taken in groups of |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
49 ## size @var{k}. |
5827 | 50 ## |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
51 ## If the first argument is a vector, @var{set}, then generate all combinations |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
52 ## of the elements of @var{set}, taken @var{k} at a time, with one row per |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
53 ## combination. The result @var{c} has @var{k} columns and |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
54 ## @w{@code{nchoosek (length (@var{set}), @var{k})}} rows. |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
55 ## |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
56 ## For example: |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
57 ## |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
58 ## How many ways can three items be grouped into pairs? |
5827 | 59 ## |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
60 ## @example |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
61 ## @group |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
62 ## nchoosek (3, 2) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
63 ## @result{} 3 |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
64 ## @end group |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
65 ## @end example |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
66 ## |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
67 ## What are the possible pairs? |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
68 ## |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
69 ## @example |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
70 ## @group |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
71 ## nchoosek (1:3, 2) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
72 ## @result{} 1 2 |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
73 ## 1 3 |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
74 ## 2 3 |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
75 ## @end group |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
76 ## @end example |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
77 ## |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
78 ## @code{nchoosek} works only for non-negative, integer arguments. Use |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
79 ## @code{bincoeff} for non-integer and negative scalar arguments, or for |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
80 ## computing many binomial coefficients at once with vector inputs for @var{n} |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
81 ## or @var{k}. |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
82 ## |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
83 ## @seealso{bincoeff, perms} |
5827 | 84 ## @end deftypefn |
85 | |
6316 | 86 ## Author: Rolf Fabian <fabian@tu-cottbus.de> |
87 ## Author: Paul Kienzle <pkienzle@users.sf.net> | |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
88 ## Author: Jaroslav Hajek |
5827 | 89 |
90 function A = nchoosek (v, k) | |
91 | |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
92 if (nargin != 2 |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
93 || !isnumeric (k) || !isnumeric (v) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
94 || !isscalar (k) || ! (isscalar (v) || isvector (v))) |
6316 | 95 print_usage (); |
5827 | 96 endif |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
97 if (k < 0 || k != fix (k) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
98 || (isscalar (v) && (v < k || v < 0 || v != fix (v)))) |
14062
5b49cafe0599
Use non-negative, non-positive with hyphens in error messages.
Rik <octave@nomad.inbox5.com>
parents:
11587
diff
changeset
|
99 error ("nchoosek: args are non-negative integers with V not less than K"); |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
100 endif |
5827 | 101 |
6318 | 102 n = length (v); |
103 | |
104 if (n == 1) | |
8506 | 105 ## Improve precision at next step. |
106 k = min (k, v-k); | |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
107 A = round (prod ((v-k+1:v)./(1:k))); |
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
108 if (A*2*k*eps >= 0.5) |
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
109 warning ("nchoosek", "nchoosek: possible loss of precision"); |
8391
343f0fbca6eb
implement nchoosek without recursion
Jaroslav Hajek <highegg@gmail.com>
parents:
8361
diff
changeset
|
110 endif |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
111 elseif (k == 0) |
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
112 A = []; |
6318 | 113 elseif (k == 1) |
114 A = v(:); | |
8404
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
115 elseif (k == n) |
868149aac690
nchoosek checks, warning, corner cases and tests
Francesco Potortì <pot@gnu.org>
parents:
8391
diff
changeset
|
116 A = v(:).'; |
8391
343f0fbca6eb
implement nchoosek without recursion
Jaroslav Hajek <highegg@gmail.com>
parents:
8361
diff
changeset
|
117 elseif (k > n) |
343f0fbca6eb
implement nchoosek without recursion
Jaroslav Hajek <highegg@gmail.com>
parents:
8361
diff
changeset
|
118 A = zeros (0, k, class (v)); |
10800 | 119 elseif (k == 2) |
120 ## Can do it without transpose. | |
121 x = repelems (v(1:n-1), [1:n-1; n-1:-1:1]).'; | |
122 y = cat (1, cellslices (v(:), 2:n, n*ones (1, n-1)){:}); | |
123 A = [x, y]; | |
124 elseif (k < n) | |
125 v = v(:).'; | |
126 A = v(k:n); | |
127 l = 1:n-k+1; | |
128 for j = 2:k | |
129 c = columns (A); | |
130 cA = cellslices (A, l, c*ones (1, n-k+1), 2); | |
131 l = c-l+1; | |
132 b = repelems (v(k-j+1:n-j+1), [1:n-k+1; l]); | |
133 A = [b; cA{:}]; | |
134 l = cumsum (l); | |
135 l = [1, 1 + l(1:n-k)]; | |
8391
343f0fbca6eb
implement nchoosek without recursion
Jaroslav Hajek <highegg@gmail.com>
parents:
8361
diff
changeset
|
136 endfor |
10800 | 137 clear cA b; |
138 A = A.'; | |
6318 | 139 endif |
8361
cf620941af1a
Set max_recursion_depth and use a subfunction in nchoosek
Francesco Potortì <pot@gnu.org>
parents:
7017
diff
changeset
|
140 endfunction |
6318 | 141 |
14090
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
142 |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
143 %!assert (nchoosek (80,10), bincoeff (80,10)) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
144 %!assert (nchoosek(1:5,3), [1:3;1,2,4;1,2,5;1,3,4;1,3,5;1,4,5;2:4;2,3,5;2,4,5;3:5]) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
145 |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
146 %% Test input validation |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
147 %!warning nchoosek (100,45); |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
148 %!error nchoosek ("100", 45) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
149 %!error nchoosek (100, "45") |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
150 %!error nchoosek (100, ones (2,2)) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
151 %!error nchoosek (repmat (100, [2 2]), 45) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
152 %!error nchoosek (100, -45) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
153 %!error nchoosek (100, 45.5) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
154 %!error nchoosek (100, 145) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
155 %!error nchoosek (-100, 45) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
156 %!error nchoosek (100.5, 45) |
281ecc6fb431
nchoosek.m: Update documentation, fix input validation, add more %!tests
Rik <octave@nomad.inbox5.com>
parents:
14062
diff
changeset
|
157 |