Creating a number pattern based on the length of array, the example is small just showing what it would look like if the array had a size of 5,6 or 7. (the actually length of arrays will be around 400,000)
How can I go about getting this numerical pattern. I was thinking it looked a little like Pascal's Triangle but the numbers are off.
I'm using Octave 3.8.1 which is like Matlab
example: If an array has the length of 5 the series would be
a1=[1 1 1;1 2 2;1 2 3;1 2 2;1 1 1]
a2=[1 1 1;2 2 1;3 2 1;2 2 1;1 1 1]
example: If an array has the length of 6 the series would be
a1=[1 1 1;1 2 2;1 2 3;1 2 3;1 2 2;1 1 1]
a2=[1 1 1;2 2 1;3 2 1;3 2 1;2 2 1;1 1 1]
example: If an array has the length of 7 the series would be
a1=[1 1 1 1;1 2 2 2;1 2 3 3;1 2 3 4;1 2 3 3;1 2 2 2;1 1 1 1]
a2=[1 1 1 1;2 2 2 1;3 3 2 1;4 3 2 1;3 3 2 1;2 2 2 1;1 1 1 1]
See image below:
This should be quite fast:
n = 9;
a1 = bsxfun(#min, min(1:n,n:-1:1).', 1:ceil(n/2));
a2 = a1(:,end:-1:1);
This does what you want:
n = 7;
a1 = cumsum(tril(ones(ceil(n/2))), 2);
a1 = a1([1:end end-mod(n,2):-1:1],:);
a2 = fliplr(a1);
A slighty different approach:
For m = ceil(n/2); the bsxfun can be substituted by
X = gallery('minij',m);
which is equal to:
X = bsxfun(#min, 1:m,(1:m).')
so you get a single block and you just need to concatenate the output.
a1 = [X; flipud(X)]
if n ~= 2*m; a1(m,:) = []; end %// clear one row if necessary
a2 = fliplr(a1)
for n = 6 you get
a1 =
1 1 1
1 2 2
1 2 3
1 2 3
1 2 2
1 1 1
and a2 accordingly mirrored. and for n = 5
a1 =
1 1 1
1 2 2
1 2 3
1 2 2
1 1 1
Related
In Matlab I would like to do a sort on color values in a particular order.
Say for instance, Sort by Hue, then Sat, then Intensity (V). Or, by V, H then S.
Something like this:
% UNSORTED
A(:,:,1) = [1 1 1 1 1 2 2 2 1 1 1];
A(:,:,2) = [1 1 1 1 1 3 2 2 3 2 2];
A(:,:,3) = [3 1 4 3 2 1 2 1 1 2 1];
% RESULT
A(:,:,1) = [1 1 1 1 1 1 1 1 2 2 2]
A(:,:,2) = [1 1 1 1 1 2 2 3 2 2 3]
A(:,:,3) = [1 2 3 3 4 1 2 1 1 2 1]
I've struggled a day on this with no luck. Any help?
One method could be:
% UNSORTED
A(:,:,1) = [1 1 1 1 1 2 2 2 1 1 1];
A(:,:,2) = [1 1 1 1 1 3 2 2 3 2 2];
A(:,:,3) = [3 1 4 3 2 1 2 1 1 2 1];
for ii = 1:size(A,1)
A(ii,:,:) = reshape(sortrows(squeeze(A(ii,:,:)),[1:3]),[1,size(A,2),size(A,3)])
end
So we extract each 2D matrix, we use squeeze to delete the singleton dimension, then we use sortrows to sort each rows (with this priority 1->2->3). And finally we reshape this 2D matrix to restore the singleton dimension and obtain a 3D matrix.
If B=[1; 2] and A=[B B B...(n times B)], how to obtain the matrix C corresponding to all the possible combinations between the column vectors of A .i.e. I want to get the combinations between n copies of the same vector.
For example, for n=3:
A =
1 1 1
2 2 2
So, C can be obtained using the function from File Exchange 'allcomb(varargin)':
C=allcomb(A(:,1),A(:,2),A(:,3))
C =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
In my case n is variable. How to obtain C for any value of n?
You can put the repetitions in a cell, and use the {:} syntax to put all cell elements as inputs to allcomb
n = 3;
B = [1,2];
A = repmat( {B}, n, 1 );
C = allcomb( A{:} ); % allcomb is FileExchange.
% combvec is a documented alternative.
Output:
C =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
Since the alphabets for each of the places is the same, this is really a base conversion. MATLAB only accepts integer bases, but we can use that integer as an index into the alphabet B:
B=[1; 2];
n = 3;
b = numel(B);
for k = 0:(b^n-1) % loop over all possible combinations
C(k+1,:) = dec2base(k, b, n);
end
C = C - '0' + 1; % convert 0..b-1 (in chars) into 1..b (in ints) for indexing
C = B(C); % index into alphabet B
Results:
>> C
C =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
The last line of the script doesn't appear to do much in this case because the alphabet happens to be the same range as our indices, but changing the alphabet to B = [7; 14] will correctly result in:
C =
7 7 7
7 7 14
7 14 7
7 14 14
14 7 7
14 7 14
14 14 7
14 14 14
Funnily enough, allcomb from MATLAB File Exchange seems to be what you want.
allcomb([1; 2],[1; 2], [1; 2])
ans =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
To do it for any n, simply construct the matrix with:
>> n = 3;
>> repmat(B, 1, n)
ans =
1 1 1
2 2 2
So i have two very long matrices. A sample is given below:
First_Matrix:
A = [...
1 1 1;
1 1 2;
1 1 3;
1 2 1;
1 2 2;
1 2 3;
1 3 1;
1 3 2;
1 3 3];
Second Matrix
B = [...
1 1 916;
1 2 653;
1 3 114];
And I would like a thirds matrix that would combine the first matrix with the third column of the second matrix, based on the values in the first two column of the 2 matrices matching (being the same).
So Ouput_Matrix:
C = [...
1 1 1 916;
1 1 2 916;
1 1 3 916;
1 2 1 653;
1 2 2 653;
1 2 3 653;
1 3 1 114;
1 3 2 114;
1 3 3 11];
What would be the best way to do this?
Thanks in advance
Use the second output of ismember with the 'rows' option to get the indices of the matching, from which you can easily build the result:
[~, ind] = ismember(A(:, [1 2]), B(:, [1 2]), 'rows');
C = [A B(ind, 3)];
The for loop isn't pretty and might slow you down if B is very long. But I don't think it's possible to avoid (edit: it seems it is).
A = [1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3];
B = [1 1 916
1 2 653
1 3 114];
C = [A zeros(size(A,1),1)];
for i = 1:size(B,1)
C(all(B(i,1:2)==A(:,1:2),2),4) = B(i,3);
end
C =
1 1 1 916
1 1 2 916
1 1 3 916
1 2 1 653
1 2 2 653
1 2 3 653
1 3 1 114
1 3 2 114
1 3 3 114
It is possible to achieve what you want without a for loop, but it may not be the most optimal implementation:
n = size(B, 1); % number of rows in B
B_(1, :, :) = B'; % convert to 3D matrix to be able to use elementwise comparision
x = squeeze(all(bsxfun(#eq, A(:, 1:2), B_(1, 1:2,:)), 2)); % x(i, j) == 1 if row A(i, :) matches B(j, :)
index = x * (1:n)'; % row B(index(i), :) corresponds with row A(i, :)
A(:, 4) = B(index, 3); % add data to A
An alternative formulation for x, without conversion to 3D, is:
x = bsxfun(#eq, A(:, 1), B(:,1)') & bsxfun(#eq, A(:, 2), B(:,2)');
The disadvantage of this method is that it less extendable to more matching columns.
given matrix A of size 6 by 6 contain blocks of numbers,each block of size 2 by 2, and outher reference matrix R of size 2 by 12 also contain blocks of numbers, each block of size 2 by 2. the perpse of the whole process is to form a new matrix, called the Index matrix, contain index's that refer to the position of the blocks within the matrix A based on the order of the blocks within the reference matrix R. and here is an exemple
matrix A:
A =[1 1 2 2 3 3;
1 1 2 2 3 3;
1 1 3 3 4 4;
1 1 3 3 4 4;
4 4 5 5 6 6;
4 4 5 5 6 6 ]
matrix R:
R=[1 1 2 2 3 3 4 4 5 5 6 6;
1 1 2 2 3 3 4 4 5 5 6 6 ]
the new matrix is:
Index =[1 2 3;
1 3 4;
4 5 6]
any ideas ?
With my favourite three guys - bsxfun, permute, reshape for an efficient and generic solution -
blksz = 2; %// blocksize
num_rowblksA = size(A,1)/blksz; %// number of blocks along rows in A
%// Create blksz x blksz sized blocks for A and B
A1 = reshape(permute(reshape(A,blksz,num_rowblksA,[]),[1 3 2]),blksz^2,[])
R1 = reshape(R,blksz^2,1,[])
%// Find the matches with "bsxfun(#eq" and corresponding indices
[valid,idx] = max(all(bsxfun(#eq,A1,R1),1),[],3)
%// Or with PDIST2:
%// [valid,idx] = max(pdist2(A1.',reshape(R,blksz^2,[]).')==0,[],2)
idx(~valid) = 0
%// Reshape the indices to the shapes of blocked shapes in A
Index = reshape(idx,[],num_rowblksA).'
Sample run with more random inputs -
>> A
A =
2 1 1 2
1 2 2 1
1 1 1 1
2 2 2 2
1 2 2 1
1 2 1 1
>> R
R =
2 1 1 1 1 2 2 2 1 1 1 1
2 1 2 1 1 2 2 1 2 2 2 1
>> Index
Index =
0 0
5 5
3 0
I need to transform a matrix:
X = [1 2; 3 4]
X = 1 2
3 4
to
X = [1 2; 1 2; 1 2; 3 4; 3 4; 3 4]
X = 1 2
1 2
1 2
3 4
3 4
3 4
and do this operation for a matrix with any number of rows.
How can I achieve this in MATLAB?
Here is a nice and easy way to do this using kron
kron(X,[1 1 1]')
this produces
1 2
1 2
1 2
3 4
3 4
3 4