function vout=nextchoose(v,w)
%NEXTCHOOSE find the next choice of k elements from a vector (with possible repeats)
% usage: vout = nextchoose(v,w)
%
% NEXTCHOOSE(V,W), where V is a row or column vector of integers in W,
% returns the next choice of length(V) elements from W by lexical ordering
% (see below) or [] if there is none. W can also be specified as a
% positive integer N, in which case W=1:N.
%
% NEXTCHOOSE can be used to iterate through all unique k-combinations in
% 1:N but keep in mind that the number is nchoosek(N,length(V))
%
% In the set of all k-combinations of W, with lexical order:
% - V is equivalent to sort(V)
% - pairs are ordered according to the first sorted elements that differ
% - the "first" choice is V0=W(1:k) (if W is sorted)
% - the "last" choice is V1=W(N-k+1:N) (if W is sorted, and N=numel(W))
% - the successor of V is determined according to the rightmost elements
% such that V(i)=W(j) and j < N-(k-i). Then V(i:k) -> W(j+1:j+k-i+1)
%
% Example 1:
% nextchoose([1,2,3],4) % returns [1,2,4]
% nextchoose([1,2,4],4) % returns [1,3,4]
% nextchoose([1,3,4],4) % returns [2,3,4]
% nextchoose([2,3,4],4) % returns []
%
% Example 2: choose 2 elements from a vector with repeats
% nextchoose([1,2],[1,2,2,3]) % returns [1,3]
% nextchoose([1,3],[1,2,2,3]) % returns [2,2]
% nextchoose([2,2],[1,2,2,3]) % returns [2,3]
% nextchoose([2,3],[1,2,2,3]) % returns []
%
% Example 3: determine all 4-combinations of 1:8
% n=8;
% k=4;
% v=1:k;
% M=zeros(nchoosek(n,k),k);
% i=0;
% while ~isempty(v),
% i=i+1;
% M(i,:)=v;
% v=nextchoose(v,n);
% end;
% isequal(M,sortrows(nchoosek(1:n,k))) % =1
% Author: Ben Petschel 25/6/2009
%
% Change history:
% 25/6/2009 - first release (modelled after nextperm.m)
% 29/6/2009 - added support for general choice vectors
vout = sort(v);
k = length(v);
if isscalar(w),
W = 1:w;
else
W = sort(w);
end;
% find the rightmost element that can be increased
ind = find(vout<W(end-k+1:end),1,'last');
if isempty(ind),
% v is the last vector
vout = [];
else
% increment vout(ind) and update the tail elements
j = find(vout(ind)==W,1,'last');
if isempty(j),
error('an element of V is not in W');
end;
vout(ind:k) = W(j+1:j+k-ind+1);
end;