88 lines
2.6 KiB
Mathematica
88 lines
2.6 KiB
Mathematica
|
function A = allcomb(varargin)
|
||
|
% ALLCOMB - All combinations
|
||
|
% B = ALLCOMB(A1,A2,A3,...,AN) returns all combinations of the elements
|
||
|
% in A1, A2, ..., and AN. B is P-by-N matrix is which P is the product
|
||
|
% of the number of elements of the N inputs.
|
||
|
% Empty inputs yields an empty matrix B of size 0-by-N. Note that
|
||
|
% previous versions (1.x) simply ignored empty inputs.
|
||
|
%
|
||
|
% Example:
|
||
|
% allcomb([1 3 5],[-3 8],[0 1]) ;
|
||
|
% 1 -3 0
|
||
|
% 1 -3 1
|
||
|
% 1 8 0
|
||
|
% ...
|
||
|
% 5 -3 1
|
||
|
% 5 8 0
|
||
|
% 5 8 1
|
||
|
%
|
||
|
% ALLCOMB(A1,..AN,'matlab') causes the first column to change fastest.
|
||
|
% This is more consistent with matlab indexing. Example:
|
||
|
% allcomb(1:2,3:4,5:6,'matlab') %->
|
||
|
% 1 3 5
|
||
|
% 2 3 5
|
||
|
% 1 4 5
|
||
|
% ...
|
||
|
% 2 4 6
|
||
|
%
|
||
|
% This functionality is also known as the cartesian product.
|
||
|
%
|
||
|
% See also NCHOOSEK, PERMS,
|
||
|
% and COMBN (Matlab Central FEX)
|
||
|
|
||
|
% for Matlab R13+
|
||
|
% version 2.1 (feb 2011)
|
||
|
% (c) Jos van der Geest
|
||
|
% email: jos@jasen.nl
|
||
|
|
||
|
% History
|
||
|
% 1.1 (feb 2006), removed minor bug when entering empty cell arrays;
|
||
|
% added option to let the first input run fastest (suggestion by JD)
|
||
|
% 1.2 (jan 2010), using ii as an index on the left-hand for the multiple
|
||
|
% output by NDGRID. Thanks to Jan Simon, for showing this little trick
|
||
|
% 2.0 (dec 2010). Bruno Luong convinced me that an empty input should
|
||
|
% return an empty output.
|
||
|
% 2.1 (feb 2011). A cell as input argument caused the check on the last
|
||
|
% argument (specifying the order) to crash.
|
||
|
|
||
|
error(nargchk(1,Inf,nargin)) ;
|
||
|
|
||
|
% check for empty inputs
|
||
|
q = ~cellfun('isempty',varargin) ;
|
||
|
if any(~q),
|
||
|
warning('ALLCOMB:EmptyInput','Empty inputs result in an empty output.') ;
|
||
|
A = zeros(0,nargin) ;
|
||
|
else
|
||
|
|
||
|
ni = sum(q) ;
|
||
|
|
||
|
argn = varargin{end} ;
|
||
|
ischar(argn)
|
||
|
if ischar(argn) && (strcmpi(argn,'matlab') || strcmpi(argn,'john')),
|
||
|
% based on a suggestion by JD on the FEX
|
||
|
ni = ni-1 ;
|
||
|
ii = 1:ni ;
|
||
|
q(end) = 0 ;
|
||
|
else
|
||
|
% enter arguments backwards, so last one (AN) is changing fastest
|
||
|
ii = ni:-1:1 ;
|
||
|
end
|
||
|
|
||
|
if ni==0,
|
||
|
A = [] ;
|
||
|
else
|
||
|
args = varargin(q) ;
|
||
|
if ~all(cellfun('isclass',args,'double')),
|
||
|
error('All arguments should be arrays of doubles') ;
|
||
|
end
|
||
|
if ni==1,
|
||
|
A = args{1}(:) ;
|
||
|
else
|
||
|
% flip using ii if last column is changing fastest
|
||
|
[A{ii}] = ndgrid(args{ii}) ;
|
||
|
% concatenate
|
||
|
A = reshape(cat(ni+1,A{:}),[],ni) ;
|
||
|
end
|
||
|
end
|
||
|
end
|