Extract a subarray - c

I have managed to transfer the 2d array int a 1d array to make it simpler. So given:
local table = {0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,0,30,31,32,33, 0,34,35,36,37, 0 }
How can I extract a sub-array as below?
local sub = {2,3,4,7,8,9,12,13,14,17,18,19,22,23,24}

Here's one way...
> t = {}
> for i = 7, 30, 5 do
>> for j = i, i + 2 do
>> t[#t+1] = ble[j]
>> end
>> end
> for k,v in ipairs(t) do print(k,v) end
1 2
2 3
3 4
4 7
5 8
6 9
7 12
8 13
9 14
10 17
11 18
12 19
13 22
14 23
15 24
>
I renamed your table to ble so it doesn't shadow the table library.

Related

Matlab: repeat and concatenate rows and cols into new array

I have two 4-by-4 arrays:
a1 = [ 1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16 ]
a2 = [ 17 18 19 20; 21 22 23 24; 25 26 27 28; 29 30 31 32 ]
I need to create 16-by-8 array C:
1 2 3 4 17 18 19 20
1 2 3 4 21 22 23 24
1 2 3 4 25 26 27 28
1 2 3 4 29 30 31 32
5 6 7 8 17 18 19 20
5 6 7 8 21 22 23 24
5 6 7 8 25 26 27 28
5 6 7 8 29 30 31 32
9 10 11 12 17 18 19 20
9 10 11 12 21 22 23 24
9 10 11 12 25 26 27 28
9 10 11 12 29 30 31 32
13 14 15 16 17 18 19 20
13 14 15 16 21 22 23 24
13 14 15 16 25 26 27 28
13 14 15 16 29 30 31 32
The left half (from 1st to 4th column) of the result array C should repeat 4 times i-th row of the array a1, the right half (from 5th to 8th column) should repeat 4 times the array a2.
Below is my code.
p=4
n=4
for i=1:n
b=n*i;
a=n*(i-1)+1;
for j=1:p
for k=a:b
C(k,j)=a1(i,j);
end;
end;
end;
for i=1:n
b=n*i;
a=n*(i-1)+1;
for j=p+1:2*p
l=1;
for k=a:b
C(k,j)=a2(l,j-p);
l=l+1;
end;
end;
end;
C;
size_C=size(C)
Question. Is it possible to create result array C without for-loop? Which functions can I use?
Yes it's possible.
One way of doing it is by using kron and repmat
C = [ kron(a1, ones(4,1)) repmat(a2, 4, 1)]
Perhaps the 4 should be derived from the size of one of the matrixes
You can use ndgrid to generate the row indices and then concatenate:
[ii, jj] = ndgrid(1:size(a2,1), 1:size(a1,1));
C = [a1(jj,:) a2(ii,:)];
With focus on performance, here's one using reshape and repmat -
% Store sizes
M = size(a1,1);
N = size(a2,1);
% Get the replicated version for a1 and a2 separately
parte1 = reshape(repmat(reshape(a1,1,M,[]),[N,1,1]),M*N,[])
parte2 = repmat(a2,[M,1]);
% Do columnar concatenatation for final output
out = [parte1 parte2]
Sample run on a generic case -
a1 = % 3 x 4 array
5 2 6 9
7 4 7 6
9 8 6 1
a2 = % 2 x 5 array
7 7 1 9 2
6 8 8 7 9
out =
5 2 6 9 7 7 1 9 2
5 2 6 9 6 8 8 7 9
7 4 7 6 7 7 1 9 2
7 4 7 6 6 8 8 7 9
9 8 6 1 7 7 1 9 2
9 8 6 1 6 8 8 7 9

Extract equally spaced subarrays from an array

I have an array:
v = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20];
I want to extract multiple arrays of length 3 equally spaced by 6 elements, starting at the fifth element of v, and then combine them together:
v1 = [5 6 7];
v2 = [11 12 13];
v3 = [17 18 19];
v_combined = [5 6 7 11 12 13 17 18 19];
Are there any simple ways to do this without using a for loop?
You can do it using logical indexing. You need to create an index mask like this
idx = [0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0]
which you can create like this:
idx = false(size(v))
k = 5
idx(k:end) = ~mod(floor((0:numel(v)-k)/3),2)
And finally
v_combined = v(idx)
In general for m elements spaces by n elements starting from k you can use
k=5;
m=3;
n=6;
I=1:numel(v);
v_combined = v((I>=k) & mod(I-k,n)<m)

Keep n largest values per column and set the rest to zero in MATLAB without a loop

I have a matrix of unsorted numbers and I want to keep the n largest (not necessarily unique) values per column and set the rest to zero.
I figured out how to do it with a loop:
a = [4 8 12 5; 9 2 6 18; 11 3 9 7; 8 9 12 4]
k = 2
for n = 1:4
[y, ind] = sort(a(:,n), 'descend');
a(ind(k+1:end),n) = 0;
end
a
which gives me:
a =
4 8 12 5
9 2 6 18
11 3 9 7
8 9 12 4
k =
2
a =
0 8 12 0
9 0 0 18
11 0 0 7
0 9 12 0
However when I try to eliminate the loop, I can't seem to get the indexing right, because this:
a = [4 8 12 5; 9 2 6 18; 11 3 9 7; 8 9 12 4]
k = 2
[y, ind] = sort(a, 'descend');
b = ind(k+1:end,:)
a(b) = 0
which gives me this: (which is not what I wanted to do)
a =
4 8 12 5
9 2 6 18
11 3 9 7
8 9 12 4
k =
2
b =
4 3 3 1
1 2 2 4
a =
0 8 12 5
0 2 6 18
0 3 9 7
0 9 12 4
Am I indexing this wrong? Do I have to use the loop?
I referenced this question to get started but it wasn't exactly what I was trying to do: How to find n largest elements in an array and make the other elements zero in matlab?
You're very close. ind in the sort function gives you the row locations for each column where that particular value would appear in the sorted output. You need to do some additional work if you want to index into the matrix properly and eliminate the entries. You know that for each column of I, that tells you that we need to eliminate those entries from that particular column. Therefore, what I would do is generate column-major linear indices using each column of I to be the rows we need to eliminate.
Try doing this:
a = [4 8 12 5; 9 2 6 18; 11 3 9 7; 8 9 12 4];
k = 2;
[y, ind] = sort(a, 'descend');
%// Change here
b = sub2ind(size(a), ind(k+1:end,:), repmat(1:size(a,2), size(a,1)-k, 1));
a(b) = 0;
We use sub2ind to help us generate our column major indices where the rows are denoted by the values in ind after the kth element and the columns we need are for each column in this matrix. There are size(a,1)-k rows remaining after you truncate out the k values after sorting, and so we generate column values that go from 1 up to as many columns as we have in a and as many rows as there are remaining.
We get this output:
>> a
a =
0 8 12 0
9 0 0 18
11 0 0 7
0 9 12 0
Here's one using bsxfun -
%// Get descending sorting indices per column
[~, ind] = sort(a,1, 'descend')
%// Get linear indices that are to be set to zeros and set those in a to 0s
rem_ind = bsxfun(#plus,ind(n+1:end,:),[0:size(a,2)-1]*size(a,1))
a(rem_ind) = 0
Sample run -
a =
4 8 12 5
9 2 6 18
11 3 9 7
8 9 12 4
n =
2
ind =
3 4 1 2
2 1 4 3
4 3 3 1
1 2 2 4
rem_ind =
4 7 11 13
1 6 10 16
a =
0 8 12 0
9 0 0 18
11 0 0 7
0 9 12 0

how do I combine only the vectors - Matlab

How do I combine all the vectors in small subsets of vectors in Matlab?
a= [5 6 7] b = [8 9 10] c=[11 12 13] d=[14 15 16] e=[17 18 19]
a combine with b and c:
Outcome:
M1= [ 5 6 7 8 9 10 11 12 13]
a with b and d:
M2 = [5 6 7 8 9 10 14 15 16]
and so on .....
This answer covers the case for an arbitrary number of vectors. The vectors are assumed to be row vectors of equal length.
Let your example data be defined as
a = [5 6 7]; b = [8 9 10]; c = [11 12 13]; d = [14 15 16]; e = [17 18 19];
vectors = {a, b, c, d, e}; %// cell array with any number of row vectors of equal size
n = 3; %// desired subset size
Then: generate all combinations of indices, use that to index into vectors, concatenate into one big row vector, and reshape that to obtain the desired result:
combs = nchoosek(1:numel(vectors), n);
result = reshape([vectors{combs.'}], numel(vectors{1})*n, []).';
This gives a matrix whose first row is your M1, second row is M2 etc:
result =
5 6 7 8 9 10 11 12 13
5 6 7 8 9 10 14 15 16
5 6 7 8 9 10 17 18 19
5 6 7 11 12 13 14 15 16
5 6 7 11 12 13 17 18 19
5 6 7 14 15 16 17 18 19
8 9 10 11 12 13 14 15 16
8 9 10 11 12 13 17 18 19
8 9 10 14 15 16 17 18 19
11 12 13 14 15 16 17 18 19
You can use the cat function:
res = cat(2,a,b,c);
or simply the [] syntax:
res = [a b c];
In both cases, res will contain [5 6 7 8 9 10 11 12 13].
Best,
Use nchoosek.
a = [5 6 7]; b = [8 9]; c = [11 12 13]; d = [14 15 16]; e = [17 18 19];
N = 3;
x = {a,b,c,d,e};
y = nchoosek(x,N);
And you have all the combination of your arrays taken N at a time in a cell array. Each row i of the cell x is a combination, so to have it back as a row vector just do
horzcat(y{i,:})
Or, if you want to get them all and put them in a cell array of size n_combs
n_combs = size(y,1);
out = cell(0,n_combs);
for i = 1 : n_combs
out{i} = horzcat(1, y{i,:});
end
There is no constraint on the size of the arrays that you want to combine, e.g., you can combine
a = [5 7]; b = [8 9]; c = [11]; d = [20 14 15 16]; e = [17 18 19];
However, if you must put together all the combination in a matrix, then the arrays have to be of the same size. In this case Luis Mendo's answer does the job.
Finally, if repetitions are allowed use nmultichoosek instead of nchoosek.

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

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

Resources