What is the meaning of the addition at the end of this array declaration? - arrays

I'm tasked with implementing an algorithm which was supplied as Matlab (which none of us have any experience with) into our c++ application.
There is an array declared as such:
encrypted = [18 10 20 13 6 25 21 13 17;
2 26 4 29 22 9 5 29 1;
19 11 21 12 7 24 20 12 16;
% ... many rows like this ...
13 21 11 18 25 6 10 18 14]+1;
What is the semantic meaning of the +1 at the end of the array declaration?

Simply adding 1 to each entry:
>> [1 2 3; 4 5 6]
ans =
1 2 3
4 5 6
>> [1 2 3; 4 5 6] + 1
ans =
2 3 4
5 6 7
If you have MATLAB around, you could have figured that out by just trying. If you do not, I hope you have a very clear picture of what the code is doing and write a good test suite, since you won't be able to compare your new code's output to the MATLAB one.

The +1 means that all elements of the written matrix will be increased by one.
Example
out = [1 2;
3 4] + 1;
disp(out)
2 3
4 5

Related

How can I need multiply group of elements instead of one element in matrices multiplication

Suppose I have a matrix of dimension [4x4], and a vector of [16x1], I need to multiply every 4 element in the vector in one element in the matrix, (instead of multiplying element in row by element in vector), how can I do that using loop ?
For example here below, the results of the first four elements in the resulted vector as shown in the below example, then the same thing for the second, third and fourth rows in the matrix. :
So the results in that example is supposed to be [16x1]
Thank you
Using kron you can use this one-liner:
%A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
%v = [2 2 2 2 0 0 0 0 1 1 1 1 3 3 3 3].';
sum(kron(A,ones(4,4)).'.*v).'/4
I use the kronecker tensor product to "replicate" 4x4 time the A matrice. After that it's pure algebra.
This is just matrix multiplication in disguise... If your tall vector was a matrix of the same size as the matrix shown, where each highlighted block is a row, it's matrix multiplication. We can set this up, then reshape back into a vector.
You can use indexing to turn this into simple matrix multiplication. A question I answered already today details how the below indexing works using bsxfun, then we just reshape at the end:
% Setup
A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
v = [2 2 2 2 0 0 0 0 1 1 1 1 3 3 3 3].';
% Matrix mutliplication
r = numel(v)/size(A,1);
b = A * v( bsxfun( #plus, (1:r:numel(v)).', 0:r-1 ) );
% Make result a column vector
b = reshape( b.', [], 1 );
See if this is what you want:
A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
v = [2 2 2 2 0 0 0 0 1 1 1 1 3 3 3 3].';
r = reshape(sum(bsxfun(#times, permute(A, [3 2 1]), permute(reshape(v, 1, [], size(A,2)), [2 3 1])), 2), [], 1);
which gives
r =
17
17
17
17
41
41
41
41
65
65
65
65
89
89
89
89
There are details that I assumed, but this shoudl do the trick:
A=reshape(1:16,4,4).';
b=repelem([2,0,1,3],1,4).';
c=[];
for row=1:size(A,1)
c=[ c; sum(reshape(repelem(A(row,:),4).*b.',4,[]),2)];
end
I am assuming here that your demo for the vector is just a bad example and that you wont have repeated values, otherwise an easier version can be achieved by just not doing 3/4ths of the multiplications.
If you do not have access to repelem, have a look at alterative codes that do the same thing:Element-wise array replication in Matlab

xor after applying filters on an array

We have an original array and a list of filters where each filter consists of indices which are allowed through the filter. The filters are rather nice, e.g. they are grouped for each power of 2 in the following way (the filters are upto n = 20).
1 (2^0) = 1 3 5 7 9 11 13 15 17 19
2 (2^1) = 1 2 5 6 9 10 13 14 17 18
4 (2^2) = 1 2 3 4 9 10 11 12 17 18 19 20
8 (2^3) = 1 2 3 4 5 6 7 8 17 18 19 20
I hope you get the idea. Now we would apply some or all of these filters (user dictates which filters to apply) to the original array and the xor of the elements of the transformed array is the answer. To take an example if the original array would have been [3 7 8 1 2 9 6 4 11] e.g. n = 9 and we needed to apply the filters of 4, 2 and 1, the transformations would be like this.
After applying filter of 4 - [3 7 8 1 x x x x 11]
After applying filter of 2 - [3 7 x x x x x x 11]
After applying filter of 1 - [3 x x x x x x x 11]
Now the xor of 3 and 11 e.g. 8 is the answer. I can solve this O(n * no. of filters) time, but I need a better solution which might give the answer in O(no of filters) time. Is there any way to take advantage of the properties of xor and/or pre-compute the results for some and then give the answer for the filters. This is because there are many queries with filters, so I need to answer the queries in O(no of filters) time. Any kind of help will be appreciated.
It can be done in O(M) where M is the number of items that pass all filters (independent of the number of filters) by iterating over the array in a particular way, generating only the indexes that pass all the filters.
This is easier to see if you write down the examples starting at zero:
1: 0 2 4 6 8 10 12 14 16 18 (numbers that don't contain 1)
2: 0 1 4 5 8 9 12 13 16 17 (numbers that don't contain 2, etc)
4: 0 1 2 3 8 9 10 11 16 17 18 19
8: 0 1 2 3 4 5 6 7 16 17 18 19
The filters are really just a constraint on the bits of the indexes in the array. That constraint is of the form index & filters = 0, where filters is just the sum of all the individual filters (eg 1 + 2 + 4 = 7). Given a valid index i the next valid index i' can be computed with only primitive operations: i' = (i | filters) + 1 & ~filters. The idea here is to set the bits that are filtered to zero so the +1 will carry through them, then filtered bits are cleared again to make the index valid. The total effect is that the unfiltered bits are incremented and the filtered bits stay zero.
This gives a simple algorithm to iterate directly over all valid indexes. Start at 0 (which is always valid) and increment using the rule above until the end of the array is reached:
for (int i = 0; i < N; i = (i | filters) + 1 & ~filters)
// do something with array[i], like XOR them all together

Matlab: how to rank 2D array and mark the ranking in the other 2D array?

I am considering an easy algorithm to rank my 2D array and mark their rank in the same size of the 2D array.
For example, I have a matrix in below:
[0 2 15 34;
0 15 21 24;
0 3 5 8;
1 14 23 29]
The output should be as follow:
[1 5 10 16;
1 10 12 14;
1 6 7 8;
4 9 13 15]
I am kind of new to matlab, I not sure if the matlab have the functionality to directly do it. Or it would be even better if you could provide some ideas for implementing the algorithm. Thank you very much!
If I understand correctly, you want to replace each element by its rank. I offer three ways to do it; the third seems to be what you want.
Let your example data be defined as
data = [0 2 15 34;
0 15 21 24;
0 3 5 8;
1 14 23 29];
This assigns equal ranks to equal data values (as in your example), but doesn't skip ranks in that case (your example seems to do so):
[~, ~, vv] = unique(data(:));
result = reshape(vv, size(data));
With your example data, this gives
result =
1 3 8 13
1 8 9 11
1 4 5 6
2 7 10 12
This assigns different ranks to equal data values (so skipping ranks is out of the question):
[~, vv] = sort(data(:));
[~, vv] = sort(vv);
result = reshape(vv, size(data));
With your example data,
result =
1 5 11 16
2 10 12 14
3 6 7 8
4 9 13 15
This assigns equal ranks to equal data values, and in that case it skips ranks:
[~, vv] = sort(data(:));
[~, vv] = sort(vv);
[~, jj, kk] = unique(data(:), 'first');
result = reshape(vv(jj(kk)), size(data));
With your example data,
result =
1 5 10 16
1 10 12 14
1 6 7 8
4 9 13 15
Another approach, single-line: for each entry, find how many other entries are smaller, and add 1:
result = reshape(sum(bsxfun(#lt,data(:),data(:).'))+1, size(data));

Rearranging an array using for loop in Matlab

I have a 1 x 15 array of values:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
I need to rearrange them into a 3 x 5 matrix using a for loop:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
How would I do that?
I'm going to show you three methods. One where you need to have a for loop, and two others when you don't:
Method #1 - for loop
First, create a matrix that is 3 x 5, then keep track of an index that will go through your array. After, create a double for loop that will help you populate the array.
index = 1;
array = 1 : 15; %// Array we wish to access
matrix = zeros(3,5); %// Initialize
for m = 1 : 3
for n = 1 : 5
matrix(m,n) = array(index);
index = index + 1;
end
end
matrix =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
Method #2 - Without a for loop
Simply put, use reshape:
matrix = reshape(1:15, 5, 3).';
matrix =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
reshape will take a vector and restructure it into a matrix so that you populate the matrix by columns first. As such, we want to put 1 to 5 in the first column, 6 to 10 in the second and 11 to 15 in the third column. Therefore, our output matrix is in fact 5 x 3. When you see this, this is actually the transposed version of the matrix we want, which is why you do .' to transpose the matrix back.
Method #3 - Another method without a for loop (tip of the hat goes to Luis Mendo)
You can use vec2mat, and specify that you need to have 5 columns worth for your matrix:
matrix = vec2mat(1:15, 5);
matrix =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
vec2mat takes a vector and reshapes it into a matrix of as many columns as you specify in the second parameter. In this case, we need 5 columns.
For the sake of (bsx)fun, here is another option...
bsxfun(#plus,1:5,[0:5:10]')
ans =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
less readable, maybe faster, but who cares if it is such a small of an array...
A = [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ] ;
A = reshape( A' , 3 , 5 ) ;
A' = 1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

How to get an array "complement" of another?

the easiest way for me to explain what i want is with an example:
a = 1:20
b = [2,7,12,18]
Now I want c to be [1,3,4,5,6,8,...,19,20] with length 16: length(a) - length(b) of course.
Is there a way for me to get c?
You can delete array elements using x(3)=[]
c=a;
c(b)=[];
What you want is called set difference in most languages. In MATLAB, you can use the setdiff function:
a=1:20;
>> b=[2,7,12,18];
>> setdiff(a,b);
ans =
Columns 1 through 11
1 3 4 5 6 8 9 10 11 13 14
Columns 12 through 16
15 16 17 19 20

Resources