Matlab diff command with bigger step - arrays

The command diff calculates differences between two consecutive elements. Is there any way to calculates differences between two nonconsecutive elements?
For example, with
x = [1,2,3,4,5,6]
is there any command to find
[x(3)-x(1),x(4)-x(2),x(5)-x(3),x(6)-x(4)] = [2,2,2,2]
or
[x(4)-x(1),x(5)-x(2),x(6)-x(3)] = [3,3,3]
And in general, for the case of a matrix? I can write some code for this; I just wonder if there any existing command in Matlab for this?
An example of the matrix case
x = [1,2,3,4;1,3,5,7;2,4,6,8]
and we want to find
[x(1,3)-x(1,1),x(1,4)-x(1,2);x(2,3)-x(2,1),x(2,4)-x(2,2);x(3,3)-x(3,1),x(3,4)-x(3,2)] = [2,2;4,4;4,4]

For vectors
I would use convolution with kernel [1 0 ยทยทยท 0 -1], where the number of zeros depends on the desired step. This can be done with function conv:
x = [1,2,3,4,5,6]; % data
s = 2; % step
result = conv(x, [1 zeros(1,s-1) -1], 'valid');
gives
result =
2 2 2 2
For matrices or N-dimensional arrays
The above can be generalized using convn, with a kernel defined as before but oriented along the desired dimension:
x = [1,2,3,4; 1,3,5,7; 2,4,6,8]; % data
s = 2; % step
d = 2; % dimension
result = convn(x, reshape(([1 zeros(1,s-1) -1]), [ones(1,d-1) s+1 1]), 'valid');
gives
result =
2 2
4 4
4 4

I'm not aware of such a function, but you can simply set up a very simple anonymous function
stepDiff = #(x, s) x(:, s:end)-x(:, 1:end-s+1);
Will give outputs like:
x = [1, 2, 3, 4, 5, 6];
>> stepDiff(x, 2)
ans =
1 1 1 1 1
>> stepDiff(x, 4)
ans =
3 3 3
x = [1, 2, 3, 4; 1, 3, 5, 7; 2, 4, 6, 8];
>> stepDiff(x, 3)
ans =
2 2
4 4
4 4

Related

Minimum number of operations to make two arrays equal

Given 2 arrays of integers, A and B, an operation on array B is defined as follows:
B[i] = B[i]+2 and B[j] = B[j]-2, where i != j
i and j can be any indices and the above operation can be performed
any number of times such that i and j are not equal
a valid operation consists of both the addition and subtraction steps, both parts are mandatory
The array is considered equal if the frequency of all the elements is same, the array need not be ordered, find the minimum operations required
Input:
A = [ 2, 10, 14 ]
B = [ 6, 2, 18 ]
Output: 2
Explanation :
1st operation: select i=0; j=2;
B[i] += 2 i.e B[0]=8;
B[j] -= 2 i.e B[2] = 16;
B after 1st operation [8,2,16]
2nd operation: select i=0; j=2;
B[i] += 2 i.e B[0]=10;
B[j] -= 2 i.e B[2] = 14;
B after 2nd operation [10,2,14]
Order doesnt matter, so we have made the arrays equal return 2;
I am unable get an approach to solve this and couldn't find any similar questions, so posting this here, thanks in advance.
Assuming the arrays are solvable, then sort the arrays (by parity, and then by value), add up the absolute value of the deltas and divide by 4.
E.g.
A = [ 2, 10, 14 ], already sorted
B = [ 6, 2, 18 ], sorted becomes [2, 6, 18]
Sum of absolute value of deltas = 0 + 4 + 4 = 8. 8/4 = 2 so 2 moves.
A = [2, 10, 14]( % 2 == 0)
B = [2, 6, 18]( % 2 == 0)
another example
A = [1, 2, 5] -> [1, 5]( % 2 == 1) & [2]( % 2 == 0)
B = [1, 3, 4] -> [1, 3]( % 2 == 1) & [4]( % 2 == 0)
Notice that (a + k) mod k == a.
Assuming we already have a sorted array.
We divide the array into k parts, according to the mod k value of the element, then we sum all absolute differences, it's four times the answer.
k = 2
A.sort(key=lambda x: x % k)
B.sort(key=lambda x: x % k)
result = 0
n = len(A)
for i in range(n):
result += abs(A[i] - B[i])
print(result >> 2)
# A = [1, 2, 5]
# B = [1, 3, 4]
# result = 1
# A = [2, 10, 14]
# B = [6, 2, 18]
# result = 2
O(N log N) because of sorting.

How to repeat each dimension of a 3-D matrix in matlab

Say I have a 3-D matrix a of dimension [X,Y,Z],
a(:,:,1) = [1 2; 3 4];
a(:,:,2) = [5 6; 7 8];
Is there a way to repeat each entry of a, say N times and construct a new matrix, b, of dimension [X, Y, N*Z]? For example, if N=2, to have a matrix b like so,
%repeat first element of 'a' 2ce
b(:,:,1) = [1 2; 3 4];
b(:,:,2) = [1 2; 3 4];
%repeat second element of 'a' 2ce
b(:,:,3) = [5 6; 7 8];
b(:,:,4) = [5 6; 7 8];
Using a nested loop can achieve this of course, for e.g.
%not tested, but should work
b = zeros(X,Y,N*Z);
k=1;
for j=1:Z
for i=1:N
b(:,:,k) = a(:,:,j);
k=k+1;
end
end
But I'll like to know if there's an inbuilt function available for this purpose.
Create an index of the form 1,1,2,2,... (example for N=2) and use it in the third dimension:
b = a(:,:,ceil(1/N:1/N:size(a,3)));

Calculating the powers of a vector elementwise

I have a vector [x, y, ...] in Octave and I would like to take the pth powers of the elements to get the new vector [x^p, y^p, ...]. Anybody has an idea how to do this?
v = [1, 2, 3, 4, 5];
p = 2;
w = v.^p;
Output (ideone):
1 2 3 4 5
1 4 9 16 25
If you want to apply an operation element wise to a vector/matrix, prepend the operator with a dot:
b=[1,2,3,4,5,6];
b2=b.^2;

Subtract second column from two matrices based on first column

Let say I have 2 matrices A (7x2) and B (3x2)
A = [1 5;2 6;3 7;4 8;5 9;6 10;7 11]
B = [2 4;4 7;5 3]
The result that I want is:
C = [2 2;4 1;5 6]
ismember does the job too:
>> C = [B(:,1) A(ismember(A(:,1),B(:,1)),2) - B(:,2)]
C =
2 2
4 1
5 6
Or if not all of B(:,1) is in A:
[m,locs] = ismember(B(:,1),A(:,1))
C = [A(locs,1) A(locs,2) - B(m,2)]
you want intersect
that way it will work even if A doesn't have to be in order or have all numbers from 1.
A = [1 5;2 6;3 7;4 8;5 9;6 10;7 11]
B = [2 4;4 7;5 3]
[cc,ia,ib] = intersect(A(:,1),B(:,1))
C = [cc,A(ia,2)-B(ib,2)]

How do I multiply 3 vectors and obtain a 3D matrix in MATLAB?

What I'm trying to do is obtain results like the snippet below without a loop.
x = [1 2 3 4];
y = [2 3 4];
z=[7 8];
[x'*y]
for k=1:size(z, 2)
z2(:,:,k)=[x'*y]*z(k);
end
z2
Loops may slow down MATLAB, however. How do I approach the task without them?
You can just do this because z is ` vector:
bsxfun(#times, reshape(z, 1, 1, []), [x'*y])
If z was a 2D matrix itself and you wanted to do a matrix multiplication at each level then you would need to use the links I posted in my comment. But because each time you are multiplying by a scalar, you can use #times.
Have a look here. Base on this, you could do as follows:
x = [1 2 3 4];
y = [2 3 4];
z=[7 8];
% replicate [x'*y] into 3D array.
d = repmat([x'*y], [1, 1, numel(z)])
% multiplay by z vector
z2 = bsxfun(#times, d, reshape(z,[1, 1, numel(z)]))

Resources