2

B is an array. If B = [1 2 1], my expected output is: [0 0 0], [1 0 0], [1 1 0], [1 1 1], [0 1 1], etc and my function is following:

function [output] = AllCombination(B)
output = [];
for i = 0:B(1)
    for j = 0:B(2)
        for k = 0:B(3)
            output = [output; [i,j,k]];
        end
    end
end

However, B can be of any length. What should I do to make that to adapt to any length of B?

Marco
  • 985
  • 7
  • 22
  • 50
  • 3
    If I understand your question correctly, you can use the approach [here](https://stackoverflow.com/questions/21895335/generate-a-matrix-containing-all-combinations-of-elements-taken-from-n-vectors/21895344#21895344) defining `vectors = cell(1,numel(B)); for k=1:numel(B), vectors{k}=1:B(k); end` – Luis Mendo Jun 26 '17 at 08:48

2 Answers2

2
function [output] = AllCombination(B)
C = arrayfun(@(x)0:x, B, 'UniformOutput', false);
D = cell(1,numel(B));
[D{:}]=ndgrid(C{:});
output = cell2mat(cellfun(@(x)x(:), D, 'UniformOutput', false));

The first line constructs a cell array containing ranges from 0 to each of the elements of B. The second creates an empty cell array of the right size to store the outputs of the third line, which passes the ranges from step 1 into ndgrid. This constructs all the combinations of the ranges. Finally we apply cellfun to convert each into a column vector, and concatenate them with cell2mat.

Sam Roberts
  • 23,951
  • 1
  • 40
  • 64
0

Another solution:

L = prod(B+1); % length of the resulting array
output = zeros(L,length(B)); % preallocating memory
for ii = 1:length(B) % for each column of the output array
    output(:,ii) = imresize(repmat(0:B(ii),1,prod(B(1:(ii-1))+1)), [1 L], 'nearest')';
end

Explanation:

repmat(0:B(ii),1,prod(B(1:(ii-1))+1)

Repeats the sequence 0:B(ii) as many times as the product of all elements of B's before it. To take into account that the counting starts from zero we add +1 to all elements.

imresize(...,[1 L], 'nearest')';

Scales the vector then to the length of the array

Edit:

Version using interp1 instead of imresize in case you don't have the image processing toolbox:

L = prod(B+1); % length of the resulting array
output = zeros(L,length(B)); % preallocating memory
for ii = 1:length(B) % for each column of the output array
    p = prod(B(1:(ii-1))+1);
    output(:,ii) = interp1(1:(((B(ii)+1)*p)), repmat(0:B(ii),1,p), linspace(1, (((B(ii)+1)*p)), L), 'nearest');
end
Leander Moesinger
  • 2,449
  • 15
  • 28