Rotating a matrix to create a spiral order of values - matlab

How do I rotate a matrix to create a spiral order of values?
For example,
12 4 2
8 3 11
6 7 2
I am supposed to to display 12 4 2 11 2 7 6 8 3 but I don't know how to terminate at the 1st row and rotate the function 90 degrees. Thanks in advance for the help.

Hint:
Check the spiral function:
spiral(n) is an n-by-n matrix with elements ranging
from 1 to n^2 in a rectangular spiral pattern.
Use its output to build an index into the original values. You may also need sort, as well as fliplr to reverse the order of values.
See the code after you've given it a try.
x = [12 4 2; 8 3 11; 6 7 2];
t = fliplr(spiral(sqrt(numel(x))));
[~, ind] = sort(t(:));
result = fliplr(x(ind).');

A =[12 4 2;...
8 3 11;...
6 7 2];
B=[];
for ii=1:5
B = [B A(1,:)];
A(1,:)=[];
A=rot90(A);
end
B
B =
12 4 2 11 2 7 6 8 3

Related

Matlab Matrix Vector multiplication

I am totally new to Matlab and have a simple question (not that simple for me):
I have a matrix x:
x = 1 2 3
4 5 6
7 8 9
10 11 12
and a Vector y:
y = 1 2 3
Now I would like to multiply the numbers 1 to 4 by the first element of the Vector, the numbers 5 to 8 by the second element and 9 to 12 by the last element.
Can´t find a solution. Any help is highly appreciated!
Thanks Paul
If you modify your input x to set up all "groups" as columns of a new input, let's say xx, e.g. by transposing and reshaping x accordingly, you can use (element-wise) multiplication. MATLAB's implicit expansion allows such (element-wise) matrix operations. (Before MATLAB R2016b, one would need bsxfun for that.)
That would be my solution:
% Inputs
x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
y = [1 2 3]
% Transpose and reshape x to set up all "groups" as new columns
xx = reshape(x.', 4, 3)
% (Element-wise) Multiplication using implicit expansion
z = xx .* y
Output:
x =
1 2 3
4 5 6
7 8 9
10 11 12
y =
1 2 3
xx =
1 5 9
2 6 10
3 7 11
4 8 12
z =
1 10 27
2 12 30
3 14 33
4 16 36
Hope that helps!

Matlab multiply each row in matrix by different number

Say that I have a matrix:
A = [ 1 2 3 ; 4 5 6 ; 7 8 9 ; 10 11 12];
Is there a way to multiply :
row 1 by 1
row 2 by 2
row 3 by 3
and so on?
I am able to do this with for loops, however it if for an assignment where they want us to use matrices.
In the actual assignment A is filled with random number but each row which by multiplied consecutively.
Thanks, any help is much appreciated
You just need to multiply a diagonal matrix by A like so.
A = [ 1 2 3 ; 4 5 6 ; 7 8 9 ; 10 11 12];
disp(diag([1 2 3 4]) * A);
1 2 3
8 10 12
21 24 27
40 44 48
You can use bsxfun to accomplish this easily and very quickly
out = bsxfun(#times, [1 2 3 4].', A)
In newer versions of MATLAB (R2016b and newer) you can actually replace bsxfun with simply *
out = [1 2 3 4].' * A;

Two simple examples on vectorizing for loops in matlab

Unfortunately my programming skills are not that advanced and I really need to vectorize some loops to finish my thesis.
I tried to make things really clear and simple and I have the following two questions in matlab:
1.
If we have a 5x5 matrix A and we want to set the diagonal elements of this matrix to the diagonal of a matrix B, apart from diag(A)=diag(B) we could use :
for i=1:5
B(i,i)=A(i,i)
end
Now if I want to vectorize this I can not use:
i=1:5
B(i,i)=A(i,i)
In that way we assign each combination from 1:5. So, in the end we asign each element of A equal to B and not the diagonal.
Is there some way that we could assign each identical pair of (i,i)?
I tried :
i=1:5
j=1:5
B(i,find(j==i))=A(i,find(j==i))
But still does not work. I repeat I know the diag property but Im only interested on the particular problem.
2.
A similar problem is the fillowing.
b=[ones(2,2) ones(2,2)*2 ones(2,2)*3 ones(2,2)*4] ;
a = zeros(8,12);
for i=1:4
a((i-1)*2+1:(i)*2,(i-1)*3+1:(i)*3) = [8*ones(2,1) b(:,[2*(i-1)+1 2*i])];
end
Thank you for your time and for your help.
Let's bring some mask magic, shall we!
Problem #1
mask = eye(size(A))==1
A(mask) = B(mask)
For creating the mask, you can also use bsxfun -
N = size(A,1)
bsxfun(#eq,[1:N]',1:N)
Or finally, you can use linear indexing -
N = size(A,1)
A(1:N+1:N^2) = B(1:N+1:N^2)
Sample run -
>> A
A =
5 2 9 6 5
9 1 6 2 2
9 7 5 3 9
4 5 8 8 7
7 5 8 1 8
>> B
B =
5 5 2 8 2
1 1 6 5 2
7 8 5 4 4
1 8 9 8 8
1 7 6 1 8
>> mask = eye(size(A))==1;
>> A(mask) = B(mask)
A =
5 2 9 6 5
9 1 6 2 2
9 7 5 3 9
4 5 8 8 7
7 5 8 1 8
Problem #2
%// Append 8's at the start of every (2,2) block in b
b1 = reshape([8*ones(2,4) ; reshape(b,4,[])],2,[])
%// Mask where b1 values are to be put in an otherwise zeros filled array
mask = kron(eye(4,4),ones(2,3))==1
%// Initialize output arraya and set values from b1 into masked places
out = zeros(size(mask))
out(mask) = b1
For your first problem. Use logical indexing:
index = diag(ones(1,size(B,1))
B(index) = A(index)

matlab: dividing vector into overlapping chunks of fixed size

I've a vector that I would like to split into overlapping subvectors of size cs in shifts of sh. Imagine the input vector is:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
given a chunksize of 4 (cs=4) and shift of 2 (sh=2), the result should look like:
[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]
note that the input vector is not necessarily divisible by the chunksize and therefore some subvectors are discarded. Is there any fast way to compute that, without the need of using e.g. a for loop?
In a related post I found how to do that but when considering non-overlapping subvectors.
You can use the function bsxfun in the following manner:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
A = v(bsxfun(#plus,(1:cs),(0:sh:length(v)-cs)'));
Here is how it works. bsxfun applies some basic functions on 2 arrays and performs some repmat-like if the sizes of inputs do not fit. In this case, I generate the indexes of the first chunk, and add the offset of each chunck. As one input is a row-vector and the other is a column-vector, the result is a matrix. Finally, when indexing a vector with a matrix, the result is a matrix, that is precisely what you expect.
And it is a one-liner, (almost) always fun :).
Do you have the signal processing toolbox? Then the command is buffer. First look at the bare output:
buffer(v, 4, 2)
ans =
0 1 3 5 7 9 11
0 2 4 6 8 10 12
1 3 5 7 9 11 13
2 4 6 8 10 12 0
That's clearly the right idea, with only a little tuning necessary to give you exactly the output you want:
[y z] = buffer(v, 4, 2, 'nodelay');
y.'
ans =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
That said, consider leaving the vectors columnwise, as that better matches most use cases. For example, the mean of each window is just mean of the matrix, as columnwise is the default.
I suppose the simplest way is actually with a loop.
A vectorizes solution can be faster, but if the result is properly preallocated the loop should perform decently as well.
v = 1:13
cs = 4;
sh = 2;
myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;
for t = cs:sh:numel(v)
count = count+1;
myMat(count,:) = v(t-cs+1:t);
end
You can accomplish this with ndgrid:
>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
The nice thing about the second syntax of the colon operator (j:i:k) is that you don't have to calculate k exactly (e.g. 1:2:6 gives [1 3 5]) if you plan to discard the extra entries, as in this problem. It automatically goes to j+m*i, where m = fix((k-j)/i);
Different test:
>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
And a new row will form with v=1:17. Does this handle all cases as needed?
What about this? First I generate the starting-indices based on cs and sh for slicing the single vectors out of the full-length vector, then I delete all indices for which idx+cs would exceed the vector length and then I'm slicing out the single sub-vectors via arrayfun and afterwards converting them into a matrix:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(#(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')
E.g. for cs=5; sh=3; this would give:
idx =
1 3 5 7
ans =
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 10 11
Depending on where the values cs; sh come from, you'd probably want to introduce a simple error-check so that cs > 0; as well as sh < cs. sh < 0 would be possible theoretically if you'd want to leave some values out in between.
EDIT: Fixed a very small bug, should be running for different combinations of sh and cs now.

matching two matrices in matlab

Suppose I have two matrices p
p =
1 3 6 7 3 6
8 5 10 10 10 4
5 4 8 9 1 7
5 5 5 3 8 9
9 3 5 4 3 1
3 3 9 10 4 1
then after sorting the columns of matrix p into ascending order
y =
1 3 5 3 1 1
3 3 5 4 3 1
5 3 6 7 3 4
5 4 8 9 4 6
8 5 9 10 8 7
9 5 10 10 10 9
I want to know, given a value from y, what its row was in p
ex: the value 3 which is in matrix p located in row 6 column 1
then after sorting it located in matrix y in row 2 column 1
So I want at the end the values after sorting in matrix y, where it was originally in matrix p
Just use second output of sort:
[y ind] = sort(p);
Your desired result (original row of each value) is in matrix ind.
The Matlab sort command returns a second value which can be used to index into the original array or matrix. From the sort documentation:
[Y,I] = sort(X,DIM,MODE) also returns an index matrix I.
If X is a vector, then Y = X(I).
If X is an m-by-n matrix and DIM=1, then
for j = 1:n, Y(:,j) = X(I(:,j),j); end
Ok i understand exactly what you want.
I will give you my code that i write now, it is not optimal but you can optimize it or i can work with you in order to get the better code..
P and y have the same size.
[n,m]=size(p);
for L=1:m
i=1;
temp=y(i,L);
while(i<=n)
if(temp==y(i,L))
% So it is present in case i of p
disp(['It is present in line' num2str(i) ' of p']);
end
i=i+1;
end
end
Voilà!!