MATLAB Answers

nchoosek with range of k values and ordered sequential value sets

14 views (last 30 days)
Andy
Andy on 10 Aug 2018
Edited: Guillaume on 10 Aug 2018
The below:
function cnkMatAll = NChooseKRange(nVect, kRange)
% NChooseKRange
%
% Combinations of N taken as k = C of 3 taken as 2 (N = {1,2,3}, k = 2)
%
% NChooseKRange(1:3,2)
%
% ans =
%
% 1 2 % k = 2
% 1 3 % k = 2
% 2 3 % k = 2
% nVect has a range of values: it defines the elements of the N Set
%
% kRange CAN equally a range of k values (not mandatory). If k = 1:2 then:
% NChooseKRange(1:3, 1:2)
%
% ans =
%
% 1 0 % k = 1
% 2 0 % k = 1
% 3 0 % k = 1
% 1 2 % k = 2
% 1 3 % k = 2
% 2 3 % k = 2
lastVal = kRange(end);
parfor i = kRange
cnk = nchoosek(nVect, i);
cnk = padarray(cnk,[0,lastVal-i],0,'post');
cnkMat(i) = {cnk};
end
elRowSizeV = zeros(1,numel(cnkMat));
parfor nr = 1:numel(cnkMat)
el = cnkMat(nr);
elRowSizeV(nr) = size(el{1},1);
end
cumRowSize = cumsum(elRowSizeV);
cnkMatAll = zeros(cumRowSize(end), kRange(end));
for nr = 1:numel(cnkMat)
el = cnkMat(nr);
if nr == 1
cnkMatAll(1:cumRowSize(nr),:) = el{1};
else
cnkMatAll(cumRowSize(nr-1)+1:cumRowSize(nr),:) = el{1};
end
end
end
is an extension of nchoosek as can be seen. Two questions:
1) Is there a better way to obtain this and the more important one is:
2) Can nchoosek be modified such that it returns only "contiguous" value ranges ... such that line:
NChooseKRange(1:3, 1:2) => 1 3 % k = 2
does NOT get returned at all?
Or is there another that would return only contiguous values of the set N (being a subset of what nchoosek currently returns)?
Thanks!
  1 Comment
Guillaume
Guillaume on 10 Aug 2018
Is there a better way to obtain this
I find this function badly designed. What if nVect contains 0?
In my opinion, merging and padding the sets for each k is wrong, keep each one separate in a cell array:
function cnkMatAll = NChooseKRange(nVect, kRange)
%cnkMatAll: a cell array the same size as kRange
cnkMatAll = arrayfun(@(k) nchoosek(nVect, k), kRange, 'UniformOutput', false);
end
Can nchoosek be modified such that it returns only "contiguous" value ranges
It sounds like what you want is nothing like nchoosek. In particular, it sounds like your nVect input has a particular form. Otherwise, what would be the output for nVect = 1:3:12?
If all you want is vectors of continuous values of a given length then there are much faster way to generate this.

Sign in to comment.

Answers (1)

Andy
Andy on 10 Aug 2018
Edited: Andy on 10 Aug 2018
A modified version of an nchoosek sub-function might do the trick:
function P = combsCont(v,m)
%COMBS All possible combinations.
% COMBS(1:N,M) or COMBS(V,M) where V is a row vector of length N,
% creates a matrix with N!/((N-M)! M!) rows and M columns containing
% all possible combinations of N elements taken M at a time.
%
% This function is only practical for situations where M is less
% than about 15.
v = v(:).'; % Make sure v is a row vector.
n = length(v);
if n == m
P = v;
elseif m == 1
P = v.';
else
P = [];
if m < n && m > 1
for k = 1:n-m+1
Q = combsCont(v(k+1:n),m-1);
t = [v(ones(size(Q,1),1),k) Q];
P = [P; t(1,:)]; %#ok
end
end
end
end
nonetheless, open to suggestions.
Replacing nchoosek in the original NChooseKRange with combsCont, gets us:
>> NChooseKRange(1:5, 1:3)
ans =
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
1 2 0
2 3 0
3 4 0
4 5 0
1 2 3
2 3 4
3 4 5
>>

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!