left cyclic permutation - matlab

I want to make left cyclic permutation using MATLAB.
Consider matrix p :
p = [2 3 4 5];
Output :
[2 3 4 5;
3 4 5 2;
4 5 2 3;
5 2 3 4];
I hope the code is available for bigger data. Anyone please help me to make this in code using MATLAB.

A loop free alternative:
[X, Y] = meshgrid(1:numel(p));
p(mod(X+Y-2,numel(p))+1)

This is one approach:
cell2mat(arrayfun(#(n) circshift(p,[0 -n]),0:3,'uni',0).')
ans =
2 3 4 5
3 4 5 2
4 5 2 3
5 2 3 4
Note that arrayfun is really just a loop disguised as a one-liner. Thus explicitly writing out a loop to do the same thing might be equally fast/slow.

Related

Convert column matrix to multiple rows with duplicated data

In Matlab, given matrix 'a' as:
a = [1 2 3 4 5 6 7 8 9]';
but a few million rows deep, what would be the best way to convert it to the format shown in 'b'?
b = [1 2 3 4 5 6
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9]
where each row in 'b' contains N consecutive values from 'a'?
I can write a function but was wondering if there's a faster, more built-in way?
Another option is the built-in Hankel matrix, for example in your case:
hankel(1:4,4:9)
or in the general case for a vector a and block size N
hankel(a(1:N),a(N:numel(a)))
I have no idea if the implementation of hankel is better or worse than #Luis Mendo solution, so test and see which solution is better for you...
Let
a = [1 2 3 4 5 6 7 8 9].'; % data
N = 4; % block size
If you have the Image Processing Toolbox: use im2col with the 'sliding' option:
b = im2col(a(:), [N 1], 'sliding');
Or, without any toolbox: use implict expansion (or bsxfun) to create the appropriate indexing matrix:
b = a((1:numel(a)-N+1)+(0:N-1).');

Without for loop, can I generate list [1 2 3 2 3 4 3 4 5 ...] in matlab?

Unlike Python, MATLAB list generation expression is limited. In MATLAB I am only allowed to do a:b:c. Can I generate a list [1 2 3 2 3 4 3 4 5 ...] in MATLAB without using for loop?
N = 3;
M = 4;
result = reshape((1:N).'+(0:M-1), 1, []);
gives
result =
1 2 3 2 3 4 3 4 5 4 5 6
How it works
(1:N).'+(0:M-1) uses implicit expansion to create the M×N matrix
1 2 3 ... M
2 3 4 ... M+1
3 4 5 ... M+2
...
N N+1 N+2 ... N+M-1
Then reshape(..., 1, []) reshapes this matrix into a row vector, reading the elements in column-major order (down, then across).
One approach would be to make three lists [1,2,3...], [2,3,4...] and [3,4,5...] and interleave them. Alternatively, you can take advantage of the pattern: [1,2,3,4,5,6,7,8,9]-[0,0,0,2,2,2,4,4,4]=[1,2,3,2,3,4,3,4,5]. The repelem() function is useful for this kind of operation.
You can try cell2mat + arrayfun like belwn
n = 3;
m = 3;
res = cell2mat(arrayfun(#(x) x+(1:n),1:m,'UniformOutput',false));
such that
res =
2 3 4 3 4 5 4 5 6

Alter number sort / number sequence

I have an array / number sequence a=[1,2,3,4,5] and I'm trying
to create an array / number sequence that looks like a_new below:
The columns represent the orders / index the numbers should go in.
a_new=...
[1,2,3,4,5;
2,1,2,3,4;
3,3,1,2,3;
4,4,4,1,2;
5,5,5,5,1]
My thoughts where to use circshift but quickly found out that would not work.
a=[1,2,3,4,5];
for n=1:5
a_wrong(:,n)=circshift(a(:)',[0 n])(:)
end
produces
a_wrong=[
5 4 3 2 1
1 5 4 3 2
2 1 5 4 3
3 2 1 5 4
4 3 2 1 5]
Any thoughts? It doesn't need to use circshift if that won't work.
PS: I'm using Octave 4.2 which is similar to Matlab
There are probably quite a few different ways to generate this matrix. Here's one using the functions repmat, toeplitz, tril, and triu:
>> a_new = tril(repmat(a.', 1, numel(a)), -1)+triu(toeplitz(a))
a_new =
1 2 3 4 5
2 1 2 3 4
3 3 1 2 3
4 4 4 1 2
5 5 5 5 1
I'm not sure about a built-in function, but this should work;
a=[1,2,3,4,5];
a_out = ones(length(a), length(a))
for n=1:5
a_out(n,:) = [n*ones(n-1),a(n:end)]
end
I do not have Octave or MATLAB installed on my computer, so I cannot test it. This may have a silly error, forgive me for that!
You can use spdiags to generate the matrix:
n = numel(a);
a_new = spdiags([repmat(flip(a).',1,n); repmat(a,n-1,1)],(1-n):0);

Create list of vector pairs from all possible permutations of two vectors [duplicate]

This question already has answers here:
Generate a matrix containing all combinations of elements taken from n vectors
(4 answers)
Closed 8 years ago.
I'm trying to achieve a relatively simple matrix manipulation in MATLAB.
From two vectors, I would like to generate all the possible two-element pairs that could be produced. For example, given the following two vectors:
a = [1 2 3]
b = [4 5 6]
... I would hope to be able to produce the following:
c =
1 1 1 2 2 2 3 3 3
4 5 6 4 5 6 4 5 6
I understand that I could generate the above using an explicit loop (such as multiple repmat() operations), but my previous experience of MATLAB suggests that there probably is a built-in function that can achieve this more quickly...
Any suggestions?
a = [1 2 3]
a =
1 2 3
>> b = [4 5 6]
b =
4 5 6
>> c=allcomb(a,b)'
c =
1 1 1 2 2 2 3 3 3
4 5 6 4 5 6 4 5 6
You can find the allcomb function here

the fastest way to replicate a vector in two direction

I have a vector for which I want to replicate its elements in both row and column directions. I have found that using ones built-in function is faster that m-file functions repmat and kron. I have seen some examples for replicating a vector in one direction, however I could not find how to do it in both direction.
Consider the following example:
a = [1 2 3];
I want to create these matrices:
b = [1 1 1
1 1 1
2 2 2
2 2 2
3 3 3
3 3 3];
and
c = [1 2 3 1 2 3
1 2 3 1 2 3];
How can I do this with ones? It there any faster way?
In my code, the vectors to be replicated are bigger and also I have to do this for many vectors in a for loop. so I am looking for a faster way.
How about if I had a matrix to be replicated? for example:
d = [1 2 3
4 5 6];
and I want to have:
e = [1 2 3 1 2 3
4 5 6 4 5 6
1 2 3 1 2 3
4 5 6 4 5 6];
c and e are straightforward cases for repmat. b is different, the most common suggestion is to use kron(a', ones(2,3)) but here are some alternatives: A similar function to R's rep in Matlab
According to the many answers in that link, the fastest is possibly
reshape(repmat(a, 6, 1), 3, 6)'
You can do it in a simple and ricorsive way:
d = [1 2 3;
4 5 6];
while (!(STOP_CONDITION_OCCURS))
d = [d d; d d];
end;
etc.