Reputation: 1865
I have an array B of :
B=[1 2 3; 10 20 30 ; 100 200 300 ; 1000 2000 3000]
such that
B =
1 2 3
10 20 30
100 200 300
1000 2000 3000
I am using the following code to find the possible combination between these variables that are below a certain value (a constraint) -- 2000 in this case :
A=[123; 323; 12 ; 421]
SA=sum(A)
V=cell(length(B),1);
n=1;
for k = 1:length(B)
for idx = nchoosek(1:length(B), k)'
B_subset = B(idx);
if (SA + sum(B_subset) <= 2000)
V(n)={B_subset(:)}; %store them in a cell
n=n+1;
end
end
end
However I failed to combine them the way I want below.
Objective :
Find the possible combinations from B to be added with SA so that their sum is less than 2000 ?
Constraint 1 :
B
can be used at once. For example, this is NOT acceptable : [1 2 20] [2 20 30]
This is the correct one : [1 20 100] [3 200 3000]
Constraint 2 : - The answers should be stored in the cell V in only one column (as initialised in the code above).
The cell should have an output similar to the one I'm currently having :
V =
[ 100]
[ 300]
[ 200]
[2x1 double]
[2x1 double]
[2x1 double]
[3x1 double]
Upvotes: 1
Views: 1331
Reputation: 814
Changed your code just a bit and added a test below - if V is unchanged -> there were no combinations -> display that. Edited to allow saving it into cell array V
and simultaneously constructing a string for printing.
This code considers every combination of three elements from B, where each element is from a different column.
V=cell(length(B),1);
A=[123; 323; 12 ; 421];
SA=sum(A);
S = 'possible combinations :';
n = 1
for ii=1:4
for jj=1:4
if jj == ii
continue
end
for kk=1:4
if or(kk == jj,kk == ii)
continue
end
B_subset = [B(ii,1), B(jj,2), B(kk,3)];
if (SA + sum(B_subset) <= 2000)
S = [S, ' ', mat2str(B_subset)];
V{n} = B_subset;
n += 1;
end
end
end
end
if V == 'possible combinations :'
disp('No possible combinations found')
else
disp(S)
end
EDIT: adding answer to the new part of the question. In the inner-most loop the different combinations of included rows are calculated.
V = {}
for ii=1:3
for jj=1:3
for kk=1:3
for ll = 1:3
rows = [ii, jj, kk, ll]
if isequal(rows, unique(rows))
% loop for turning off individual elements
result = [B(1,ii), B(2,jj), B(3,kk), B(4,ll)]
for mm = 0:1:15
% make a binary string - will loop through all combinations of zeros and ones
str1 = dec2bin(mm,4)
mask = zeros(1,4)
for nn = 1:4 % make a numeric vector
mask(nn) = str2num(str1(nn))
end
masked_result = mask.*result
V = [V {masked_result}]
end
end
end
end
end
end
Upvotes: 1
Reputation: 32930
Here, this fix should do the trick:
SA = sum(A);
V = cell(numel(B), 1); % // Changed 'length' to 'numel'
n = 1;
for k = 1:size(B, 1) % // Changed 'length' to 'size'
for idx = nchoosek(1:numel(B), k)' %'// Changed 'length' to 'numel'
%// Ignore the combination if there are two elements from the same row
rows = mod(idx, size(B, 1));
if ~isequal(rows, unique(rows))
continue
end
B_subset = B(idx);
if (SA + sum(B_subset) <= 2000)
V(n) = {B_subset(:)};
n = n + 1;
end
end
end
Perhaps it's not the most efficient solution there is, but it's short and it works.
Upvotes: 1