I have the following problem. Let's say I have four possible values {1 2 3 4} and I want a specific behavior of mod function
The behavior I seek is this one
1 mod 4 = 1
2 mod 4 = 2
3 mod 4 = 3
4 mod 4 = 4
but I have the following results with matlab.
1 mod 4 = 1
2 mod 4 = 2
3 mod 4 = 3
4 mod 4 = 0
Are there any ideas as how to achieve the desired behavior with the simplest way possible in MATLAB?
If A holds those values, you can subtract 1, perform mod and add back 1.
Sample run -
>> A = 1:8
A =
1 2 3 4 5 6 7 8
>> mod(A-1,4)+1
ans =
1 2 3 4 1 2 3 4
How about:
function [result] = my_mod(x,y)
m = mod(x,y);
result = m+~m*y;
The ~ negates the result from mod, i.e. :
~0 == 1
~1 == 0
~2 == 0
...
So we only add y if the result from mod is 0.
demo
>> my_mod(1:8, 4)
ans =
1 2 3 4 1 2 3 4
Related
Suppose I have a list of length 2k, say {1,2,...,2k}. The number of possible ways of grouping the 2k numbers into k (unordered) pairs is n(k) = 1*3* ... *(2k-1). So for k=2, we have the following three different ways of forming 2 pairs
(1 2)(3 4)
(1 3)(2 4)
(1 4)(2 3)
How can I use Matlab to create the above list, i.e., create a matrix of n(k)*(2k) such that each row contains a different way of grouping the list of 2k numbers into k pairs.
clear
k = 3;
set = 1: 2*k;
p = perms(set); % get all possible permutations
% sort each two column
[~, col] = size(p);
for i = 1: 2: col
p(:, i:i+1) = sort(p(:,i:i+1), 2);
end
p = unique(p, 'rows'); % remove the same row
% sort each row
[row, col] = size(p);
for i = 1: row
temp = reshape(p(i,:), 2, col/2)';
temp = sortrows(temp, 1);
p(i,:) = reshape(temp', 1, col);
end
pairs = unique(p, 'rows'); % remove the same row
pairs =
1 2 3 4 5 6
1 2 3 5 4 6
1 2 3 6 4 5
1 3 2 4 5 6
1 3 2 5 4 6
1 3 2 6 4 5
1 4 2 3 5 6
1 4 2 5 3 6
1 4 2 6 3 5
1 5 2 3 4 6
1 5 2 4 3 6
1 5 2 6 3 4
1 6 2 3 4 5
1 6 2 4 3 5
1 6 2 5 3 4
As someone think my former answer is not useful, i post this.
I have the following brute force way of enumerating the pairs. Not particularly efficient. It can also cause memory problem when k>9. In that case, I can just enumerate but not create Z and store the result in it.
function Z = pair2(k)
count = [2*k-1:-2:3];
tcount = prod(count);
Z = zeros(tcount,2*k);
x = [ones(1,k-2) 0];
z = zeros(1,2*k);
for i=1:tcount
for j=k-1:-1:1
if x(j)<count(j)
x(j) = x(j)+1;
break
end
x(j) = 1;
end
y = [1:2*k];
for j=1:k-1
z(2*j-1) = y(1);
z(2*j) = y(x(j)+1);
y([1 x(j)+1]) = [];
end
z(2*k-1:2*k) = y;
Z(i,:) = z;
end
k = 3;
set = 1: 2*k;
combos = combntns(set, k);
[len, ~] = size(combos);
pairs = [combos(1:len/2,:) flip(combos(len/2+1:end,:))];
pairs =
1 2 3 4 5 6
1 2 4 3 5 6
1 2 5 3 4 6
1 2 6 3 4 5
1 3 4 2 5 6
1 3 5 2 4 6
1 3 6 2 4 5
1 4 5 2 3 6
1 4 6 2 3 5
1 5 6 2 3 4
You can also use nchoosek instead of combntns. See more at combntns or nchoosek
I have been trying to write a code where the users enters two numbers in order to get 2 columns. It is very hard to explain by words what I am trying to achieve so here is an example:
If the user inputs a = 1 and b = 1, the following table should be created:
ans =
1 1
If the user inputs a = 2 and b = 2:
ans =
1 1
1 2
2 1
2 2
If the user inputs a = 2 and b = 5:
ans =
1 1
1 2
1 3
1 4
1 5
2 1
2 2
2 3
2 4
2 5
For other values of a and b, the matrix should be constructed according to the above shown sequence.
This can be achieved straight-forward by the use of repelem and repmat:
[repelem((1:a).',b),repmat((1:b).',a,1)]
A more elegant way is using meshgrid and reshape it after:
[A,B] = meshgrid(1:a,1:b);
[A(:),B(:)]
Let's create an anonymous function and test the first approach:
>> fun = #(a,b) [repelem((1:a).',b),repmat((1:b).',a,1)];
>> fun(1,1)
ans =
1 1
>> fun(2,2)
ans =
1 1
1 2
2 1
2 2
>> fun(2,5)
ans =
1 1
1 2
1 3
1 4
1 5
2 1
2 2
2 3
2 4
2 5
Here is an alternative way
for example a = 2 and b = 5
A(1:b*a,1) = reshape(mtimes((1:a).',ones(1,b)).',1,b*a)
A(1:b*a,2) = reshape(mtimes((1:b).',ones(1,a)),1,b*a)
A =
1 1
1 2
1 3
1 4
1 5
2 1
2 2
2 3
2 4
2 5
There is just one logic, in the code below you define a matrix of row size and a and column size b
>> mtimes((1:a).',ones(1,b))
ans =
1 1 1 1 1
2 2 2 2 2
and the next step simply reshapes the matrix column wise for a and row wise for b by taking a transpose
A(1:b*a,1) = reshape(mtimes((1:a).',ones(1,b)).',1,b*a)
A(1:b*a,2) = reshape(mtimes((1:b).',ones(1,a)),1,b*a)
If I have an arbitrary n*m matrix called data and I would like to take differences of the matrix using gradually bigger steps.
The first case would have a first column equal to data(:,2)-data(:,1), the next column would be data(:,3)-data(:,2) and so on. This can be done with the following function.
data = diff(data,1,2)
Similarly I would also like to take differences based of every second column, so that the first entry would be data(:,3)-data(:,1) and the next data(:,5)-data(:,3) and so on.
This can't be done with diff, but is there any other function or method that can do it without resorting to looping?
I need to do the same thing for every n value up to 50.
Use column indexing to select the "right" columns and then use your favourite diff -
A = randi(9,4,9) %// Input array
stepsize = 2; %// Edit this for a different stepsize
out = diff(A(:,1:stepsize:end),1,2)
Output -
A =
8 9 9 8 3 2 6 8 7
2 5 5 7 5 3 9 6 3
2 7 7 2 4 1 2 4 1
6 2 1 5 4 9 9 3 7
out =
1 -6 3 1
3 0 4 -6
5 -3 -2 -1
-5 3 5 -2
I just wrote a simple wrapper function for the purpose.
function [ out ] = diffhigh( matrix, offset )
matrix_1 = matrix(:,(offset+1):size(matrix,1));
matrix_2 = matrix(:, 1:(size(matrix,1)-offset));
out = matrix_1 - matrix_2;
end
>> a
a =
3 5 1 2 4
1 2 3 4 5
1 4 5 3 2
1 2 4 3 5
2 1 5 3 4
>> diffhigh(a, 2)
ans =
-2 -3 3
2 2 2
4 -1 -3
3 1 1
3 2 -1
>> diffhigh(a, 3)
ans =
-1 -1
3 3
2 -2
2 3
1 3
I want to create a table which contains all possible combinations, order is important, of N numbers in sets of k using matlab.
I tried Combinations = combntns(set,subset) and Combinations = perms(v) and Combinations = combnk(v,k)but in those order is not important.
An example:
nchoosek(1:5,3)
ans =
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
While it should also include
1 3 2
1 4 2
1 5 2
1 3 5
1 5 3
...
The number of possible combinations is given by the following by the function:
N!/(N-k)!
source: Mathisfun.com
Is there a possible way to do it this using matlab functions?
Try this memory efficient solution:
n = 5; k = 3;
nk = nchoosek(1:n,k);
p=zeros(0,k);
for i=1:size(nk,1),
pi = perms(nk(i,:));
p = unique([p; pi],'rows');
end
p should contain what you are describing. At least size(p,1) == factorial(n)/factorial(n-k) or 60 for this example.
A = [1,4,2,5,10
2,4,5,6,2
2,1,5,6,10
2,3,5,4,2]
And I want split it into two matrix by the last column
A ->B and C
B = [1,4,2,5,10
2,1,5,6,10]
C = [2,4,5,6,2
2,3,5,4,2]
Also, this method could be applied to a big matrix, like matrix 100*22 according to the last column value into 9 groups by matlab.
Use logical indexing
B=A(A(:,end)==10,:);
C=A(A(:,end)==2,:);
returns
>> B
B =
1 4 2 5 10
2 1 5 6 10
>> C
C =
2 4 5 6 2
2 3 5 4 2
EDIT: In reply to Dan's comment here is the extension for general case
e = unique(A(:,end));
B = cell(size(e));
for k = 1:numel(e)
B{k} = A(A(:,end)==e(k),:);
end
or more compact way
B=arrayfun(#(x) A(A(:,end)==x,:), unique(A(:,end)), 'UniformOutput', false);
so for
A =
1 4 2 5 10
2 4 5 6 2
2 1 5 6 10
2 3 5 4 2
0 3 1 4 9
1 3 4 5 1
1 0 4 5 9
1 2 4 3 1
you get the matrices in elements of cell array B
>> B{1}
ans =
1 3 4 5 1
1 2 4 3 1
>> B{2}
ans =
2 4 5 6 2
2 3 5 4 2
>> B{3}
ans =
0 3 1 4 9
1 0 4 5 9
>> B{4}
ans =
1 4 2 5 10
2 1 5 6 10
Here is a general approach which will work on any number of numbers in the last column on any sized matrix:
A = [1,4,2,5,10
2,4,5,6,2
1,1,1,1,1
2,1,5,6,10
2,3,5,4,2
0,0,0,0,2];
First sort by the last column (many ways to do this, don't know if this is the best or not)
[~, order] = sort(A(:,end));
As = A(order,:);
Then create a vector of how many rows of the same number appear in that last col (i.e. how many rows per group)
rowDist = diff(find([1; diff(As(:, end)); 1]));
Note that for my example data rowDist will equal [1 3 2] as there is 1 1, 3 2s and 2 10s.
Now use mat2cell to split by these row groupings:
Ac = mat2cell(As, rowDist);
If you really want to you can now split it into separate matrices (but I doubt you would)
Ac{:}
results in
ans =
1 1 1 1 1
ans =
0 0 0 0 2
2 3 5 4 2
2 4 5 6 2
ans =
1 4 2 5 10
2 1 5 6 10
But I think you would find Ac itself more useful
EDIT:
Many solutions so might as well do a time comparison:
A = [...
1 4 2 5 10
2 4 5 6 2
2 1 5 6 10
2 3 5 4 2
0 3 1 4 9
1 3 4 5 3
1 0 4 5 9
1 2 4 3 1];
A = repmat(A, 1000, 1);
tic
for l = 1:100
[~, y] = sort(A(:,end));
As = A(y,:);
rowDist = diff(find([1; diff(As(:, end)); 1]));
Ac = mat2cell(As, rowDist);
end
toc
tic
for l = 1:100
D=arrayfun(#(x) A(A(:,end)==x,:), unique(A(:,end)), 'UniformOutput', false);
end
toc
tic
for l = 1:100
for k = 1:numel(e)
B{k} = A(A(:,end)==e(k),:);
end
end
toc
tic
for l = 1:100
Bb = sort(A(:,end));
[~,b] = histc(A(:,end), Bb([diff(Bb)>0;true]));
C = accumarray(b, (1:size(A,1))', [], #(r) {A(r,:)} );
end
toc
resulted in
Elapsed time is 0.053452 seconds.
Elapsed time is 0.17017 seconds.
Elapsed time is 0.004081 seconds.
Elapsed time is 0.22069 seconds.
So for even for a large matrix the loop method is still the fastest.
Use accumarray in combination with histc:
% Example data (from Mohsen Nosratinia)
A = [...
1 4 2 5 10
2 4 5 6 2
2 1 5 6 10
2 3 5 4 2
0 3 1 4 9
1 3 4 5 1
1 0 4 5 9
1 2 4 3 1];
% Get the proper indices to the specific rows
B = sort(A(:,end));
[~,b] = histc(A(:,end), B([diff(B)>0;true]));
% Collect all specific rows in their specific groups
C = accumarray(b, (1:size(A,1))', [], #(r) {A(r,:)} );
Results:
>> C{:}
ans =
1 3 4 5 1
1 2 4 3 1
ans =
2 3 5 4 2
2 4 5 6 2
ans =
0 3 1 4 9
1 0 4 5 9
ans =
2 1 5 6 10
1 4 2 5 10
Note that
B = sort(A(:,end));
[~,b] = histc(A(:,end), B([diff(B)>0;true]));
can also be written as
[~,b] = histc(A(:,end), unique(A(:,end)));
but unique is not built-in and is therefore likely to be slower, especially when this is all used in a loop.
Note also that the order of the rows has changed w.r.t. the order they had in the original matrix. If the order matters, you'll have to throw in another sort:
C = accumarray(b, (1:size(A,1))', [], #(r) {A(sort(r),:)} );