Given a matrix A, I have to make all possible combinations of entries of A such that only one number is selected for each row. I have made a recursive program which is running successfully. But I am not able to save the output vector. So, for example in the following matrix A, there will be 27 such combinations, I want to save them in matrix of order 3x27.
A = [3 4 0; 2 3 7; 45 7 0]
n = 1;
X = zeros(3,1);
comb(n, X, A);
%function to calculate all combinations.
function X = comb(n, X, A)
if (n > 3)
X
return
end
for i = 1:3
X(n) = A(n, i);
comb(n + 1, X, A);
end
end
Here's one of the possible approaches:
To make your variable visible in all contexts, you need to declare a global variable:
global OUT;
%rest of the code
Then, you just define OUT in you main file as empty variable:
OUT = [];
And in function script, you instruct to append X to OUT whenever the if-statement is satisfied:
if (n > 3)
OUT = [OUT,X];
return
end
The resulting code is as follows:
global OUT;
OUT = [];
A = [3 4 0; 2 3 7; 45 7 0];
n = 1;
X = zeros(3,1);
comb_SO(n, X, A);
OUT
function X = comb_SO(n, X, A)
global OUT;
if (n > 3)
OUT = [OUT,X];
return
end
for i = 1:3
X(n) = A(n, i);
comb_SO(n + 1, X, A);
end
end
The sought result is in OUT variable:
3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 0
2 2 2 3 3 3 7 7 7 2 2 2 3 3 3 7 7 7 2 2 2 3 3 3 7 7 7
45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0
But, MATLAB functionality allows your goal to be achieved without any recursion:
A = [3 4 0; 2 3 7; 45 7 0];
OUT = combvec(A(1,:),A(2,:),A(3,:))
Or, even without combvec, for arbitrary size of A:
A = reshape(1:20,4,5);
[n,m] = size(A);
Q = repmat({1:m},n,1);
B = cell(n,1);
[B{:}] = ndgrid(Q{:})
tmp = [];
OUT = [];
for k = 1:n
tmp = [tmp,B{k}(:)];
OUT = [OUT;A(k,tmp(:,k))];
end
Hope, that helps
Given a vector A that contains a sequence of numbers.
The objective is to find all series (longer than a given number "threshold") that contain the same value. The result should be the position of both first and last values of that series.
Example: given a vector A where:
A = [1 1 1 2 1 3 3 3 1 1 1 1 1 4 3 2 2 2 2 2 2 2 3 4];
and a threshold B = 5;
The results would be:
[9 13] % a series contain only the number 1 with length equal to 5
[16 22] % a series contain only the number 2 with length equal to 7
A=[1 1 1 2 1 3 3 3 1 1 1 1 1 4 3 2 2 2 2 2 2 2 3 4];
B = 5;
[l c]= size(A); % to know the size of 'A'
K=1; % to define the length of the series
W=1; % a value used to save the positions of the wanted series.
For i=1:c-1
If A(i)==A(i+1)
K=k+1;
Else
If k>= B % to test of the actual series is equal or longer than the given threshold
S(w,1)=i;
S(w,2)= S(w,1)-k+1; % saving the first position and the last position of the series in 'S'
w=w+1;
end
k=1;
end
S % the final result which is a table contain all wanted series.
the result is as follow:
S 13 9 % 13: the last position of the wanted series and 9 is the first position
16 22
This one work soo good. But still... it is soo slow when its come to a big table.
A faster, vectorized option is to modify the approach from this solution for finding islands of zeroes:
A = [1 1 1 2 1 3 3 3 1 1 1 1 1 4 3 2 2 2 2 2 2 2 3 4]; % Sample data
B = 5; % Threshold
tsig = (diff(A) ~= 0);
dsig = diff([1 tsig 1]);
startIndex = find(dsig < 0);
endIndex = find(dsig > 0)-1;
duration = endIndex-startIndex+1;
stringIndex = (duration >= (B-1));
result = [startIndex(stringIndex); endIndex(stringIndex)+1].';
And the results:
result =
9 13
16 22
I have two matrices, one of which (Let's say matrix H) is 4x2 and the other one (matrix N) is 100x2.
I want to make a combination for every pair of N, containing every pair of H.
Basically, if my
H = [2 2; 2 4; 4 2; 4 4]
N = [1 1; 1 2; 1 3; ...;
10 8; 10 9; 10 10]
I would like to have a final matrix
M = [1 2 2 1; 1 2 4 1; 1 4 2 1; 1 4 4 1; 1 2 2 2; 1 2 4 2; ...; 10 4 4 10]
of a size 100x4 (because every pair of N will be multiplied |H|=4 times.)
So all the pairs of H matrix will be between all pairs of my N matrix.
I hope I am clear enough.
Use the follwing syntax:
%calculates the Cartesian multipication of 1:size(h,1) and 1:size(N,1)
sets = {1:size(H,1), 1:size(N,1)};
[hInds, nInds] = ndgrid(sets{:});
%generates the output matrix
outRes = [N( nInds(:),1),H( hInds(:),1),H( hInds(:),2),N( nInds(:),2)];
Partial results (displaying just the first rows of the output):
outRes =
1 2 2 1
1 2 4 1
1 4 2 1
1 4 4 1
1 2 2 2
1 2 4 2
1 4 2 2
1 4 4 2
1 2 2 3
1 2 4 3
1 4 2 3
1 4 4 3
...
Notice that if N is 4x2 and N is 10x2, the final matrix size will be 40x4 and not 100x4 as you mentioned.
Try this:
H= [2 2; 2 4; 4 2; 4 4];
N= fix(100*(rand(10,2))) % Replace this with your N matrix
iter=0;
for i=1:10
for j=1:4
iter=iter+1;
A(iter,:)=[N(i,1), H(j,1:2), N(i,2)];
end
end
A
I am trying to match 1st column of A with 1st to 3rd columns of B, and append corresponding 4th column of B to A.
For example,
A=
1 2
3 4
B=
1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5
I compare A(:,1) and B(:, 1:3)
1 and 3 are in A(:,1)
1 is in the 1st, 2nd, 3rd rows of B(:, 1:3), so append B([1 2 3], 4:end)' to A's 1st row.
3 is in the 2nd and 4th rows of B(:,1:3), so append B([2 4], 4:end)' to A's 2nd row.
So that it becomes:
1 2 5 4 5 3 1 2
3 4 5 3 6 5 0 0
I could code this using only for and if.
clearvars AA A B mem mem2 mem3
A = [1 2 ; 3 4]
B = [1 2 4 5 4; 1 2 3 5 3; 1 1 1 1 2; 3 4 5 6 5]
for n=1:1:size(A,1)
mem = ismember(B(:,[1:3]), A(n,1));
mem2 = mem(:,1) + mem(:,2) + mem(:,3);
mem3 = find(mem2>0);
AA{n,:} = horzcat( A(n,:), reshape(B(mem3,[4,5])',1,[]) ); %'
end
maxLength = max(cellfun(#(x)numel(x),AA));
out = cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false))
I am trying to make this code efficient, by not using for and if, but couldn't find an answer.
Try this
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
row2 = mat2cell(permute(sum(ab==b,2),[3,1,2]),ones(1,numel(a)));
AA = cellfun(#(x)(reshape(B(x>0,4:end)',1,numel(B(x>0,4:end)))),row2,'UniformOutput',0);
maxLength = max(cellfun(#(x)numel(x),AA));
out = cat(2,A,cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false)))
UPDATE Below code runs in almost same time as the iterative code
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
df = permute(sum(ab==b,2),[3,1,2])';
AA = arrayfun(#(x)(B(df(:,x)>0,4:end)),1:size(df,2),'UniformOutput',0);
AA = arrayfun(#(x)(reshape(AA{1,x}',1,numel(AA{1,x}))),1:size(AA,2),'UniformOutput',0);
maxLength = max(arrayfun(#(x)(numel(AA{1,x})),1:size(AA,2)));
out2 = cell2mat(arrayfun(#(x,i)((cat(2,A(i,:),AA{1,x},zeros(1,maxLength-length(AA{1,x}))))),1:numel(AA),1:size(A,1),'UniformOutput',0));
How about this:
%# example data
A = [1 2
3 4];
B = [1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5];
%# rename for clarity & reshape for algorithm's convenience
needle = permute(A(:,1), [2 3 1]);
haystack = B(:,1:3);
data = B(:,4:end).';
%# Get the relevant rows of 'haystack' for each entry in 'needle'
inds = any(bsxfun(#eq, haystack, needle), 2);
%# Create data that should be appended to A
%# All data and functionality in this loop is local and static, so speed
%# should be optimal.
append = zeros( size(A,1), numel(data) );
for ii = 1:size(inds,3)
newrow = data(:,inds(:,:,ii));
append(ii,1:numel(newrow)) = newrow(:);
end
%# Now append to A, stripping unneeded zeros
A = [A append(:, ~all(append==0,1))]
My input is the following:
X = [1 1; 1 2; 1 3; 1 4; 2 5; 1 6; 2 7; 1 8];
X =
1 1
1 2
1 3
1 4
2 5
1 6
2 7
1 8
I am looking to output a new matrix based on the value of the first column. If the value is equal to 1 -- the output will remain the same, when the value is equal to 2 then I would like to output two of the values contained in the second row. Like this:
Y =
1
2
3
4
5
5
6
7
7
8
Where 5 is output two times because the value in the first column is 2 and the same for 7
Here it is (vectorized):
C = cumsum(X(:,1))
A(C) = X(:,2)
D = hankel(A)
D(D==0) = inf
Y = min(D)
Edit:
Had a small bug, now it works.
% untested code:
Y = []; % would be better to pre-allocate
for ii = 1:size(X,1)
Y = [Y; X(ii,2)*ones(X(ii,1),1)];
end