This repository has been archived by the owner on Jul 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
combn.m
132 lines (118 loc) · 3.96 KB
/
combn.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
function [M,IND] = combn(V,N)
% COMBN - all combinations of elements
% M = COMBN(V,N) returns all combinations of N elements of the elements in
% vector V. M has the size (length(V).^N)-by-N.
%
% [M,I] = COMBN(V,N) also returns the index matrix I so that M = V(I).
%
% V can be an array of numbers, cells or strings.
%
% Example:
% M = COMBN([0 1],3) returns the 8-by-3 matrix:
% 0 0 0
% 0 0 1
% 0 1 0
% 0 1 1
% ...
% 1 1 1
%
% All elements in V are regarded as unique, so M = COMBN([2 2],3) returns
% a 8-by-3 matrix with all elements equal to 2.
%
% NB Matrix sizes increases exponentially at rate (n^N)*N.
%
% See also PERMS, NCHOOSEK
% and ALLCOMB and PERMPOS on the File Exchange
% tested in Matlab R13, R14, 2010b
% version 4.2 (apr 2011)
% (c) Jos van der Geest
% email: [email protected]
% History
% 1.1 updated help text
% 2.0 new faster algorithm
% 3.0 (aug 2006) implemented very fast algorithm
% 3.1 (may 2007) Improved algorithm Roger Stafford pointed out that for some values, the floor
% operation on floating points, according to the IEEE 754 standard, could return
% erroneous values. His excellent solution was to add (1/2) to the values
% of A.
% 3.2 (may 2007) changed help and error messages slightly
% 4.0 (may 2008) again a faster implementation, based on ALLCOMB, suggested on the
% newsgroup comp.soft-sys.matlab on May 7th 2008 by "Helper". It was
% pointed out that COMBN(V,N) equals ALLCOMB(V,V,V...) (V repeated N
% times), ALLCMOB being faster. Actually version 4 is an improvement
% over version 1 ...
% 4.1 (jan 2010) removed call to FLIPLR, using refered indexing N:-1:1
% (is faster, suggestion of Jan Simon, jan 2010), removed REPMAT, and
% let NDGRID handle this
% 4.2 (apr 2011) corrrectly return a column vector for N = 1 (error pointed
% out by Wilson).
error(nargchk(2,2,nargin)) ;
if isempty(V) || N == 0,
M = [] ;
IND = [] ;
elseif fix(N) ~= N || N < 1 || numel(N) ~= 1 ;
error('combn:negativeN','Second argument should be a positive integer') ;
elseif N==1,
% return column vectors
M = V(:) ;
IND = (1:numel(V)).' ;
else
% speed depends on the number of output arguments
if nargout<2,
M = local_allcomb(V,N) ;
else
% indices requested
IND = local_allcomb(1:numel(V),N) ;
M = V(IND) ;
end
end
% LOCAL FUNCTIONS
function Y = local_allcomb(X,N)
% See ALLCOMB, available on the File Exchange
if N>1
% create a list of all possible combinations of N elements
[Y{N:-1:1}] = ndgrid(X) ;
% concatenate into one matrix, reshape into 2D and flip columns
Y = reshape(cat(N+1,Y{:}),[],N) ;
else
% no combinations have to be made
Y = X(:) ;
end
% =========================================================================
% Previous algorithms
% Version 3.2
% % COMBN is very fast using a single matrix multiplication, without any
% explicit for-loops.
% nV = numel(V) ;
% % use a math trick
% A = [0:nV^N-1]+(1/2) ;
% B = [nV.^(1-N:0)] ;
% IND = rem(floor((A(:) * B(:)')),nV) + 1 ;
% M = V(IND) ;
% Version 2.0
% for i = N:-1:1
% X = repmat(1:nV,nV^(N-i),nV^(i-1));
% IND(:,i) = X(:);
% end
% M = V(IND) ;
% Version 1.0
% nV = numel(V) ;
% % don waste space, if only one output is requested
% [IND{1:N}] = ndgrid(1:nV) ;
% IND = fliplr(reshape(cat(ndims(IND{1}),IND{:}),[],N)) ;
% M = V(IND) ;
% Combinations using for-loops
% can be implemented in C or VB
% nv = length(V) ;
% C = zeros(nv^N,N) ; % declaration
% for ii=1:N,
% cc = 1 ;
% for jj=1:(nv^(ii-1)),
% for kk=1:nv,
% for mm=1:(nv^(N-ii)),
% C(cc,ii) = V(kk) ;
% cc = cc + 1 ;
% end
% end
% end
% end