Replicating a vector while summing an increasing value - arrays

I have this vector:
a = [ 7 8 9 7 8 9];
and I would like to obtain the following vector:
b= [ 7 8 9 7 8 9;
17 18 19 17 18 19;
27 28 29 27 28 29;
37 38 39 37 38 39 ...]
I am replicating the vector and then summing 10 for each line (for n lines). I would like to do this without using loop iterations. How can I do it?
Thank you so much.

My first bsxfun solution.
a = [ 7 8 9 7 8 9];
b = 0:10:(10+10*n);
c = bsxfun(#plus,a,b.');
c =
7 8 9 7 8 9
17 18 19 17 18 19
27 28 29 27 28 29
37 38 39 37 38 39
47 48 49 47 48 49
57 58 59 57 58 59
67 68 69 67 68 69
77 78 79 77 78 79
87 88 89 87 88 89
97 98 99 97 98 99
107 108 109 107 108 109
Bit of explanation, though a full and complete introduction to bsxfun can be found in this answer by Divakar.
What happens is that your row array a gets piece-wise added to the column vector b. Thus the first element of a, being 7 in this case, gets added to the column vector b=[10;20;30;...] and becomes the first column of your output matrix c. The second entry of a is summed with the same column vector b and becomes the second column of c. This gets repeated to fill the entire matrix c to a size of numel(b) x numel(a).
This is becoming quite the coding fest. I ran some bench test, running a loop with n=1000 a hundred times and averaged the results. Windows 7, MATLAB R2012a, i5-750 CPU. Actually, the for loop is not even the worst in terms of timing:
bsxfun: 0.00003556 s.
repmat: 0.00048514 s.
cumsum: 0.00015726 s.
for : 0.00033096 s.
Timing revisited on the same system, but with MATLAB R2015a. for is now the slowest, with the others edging towards one another, but bsxfun prevails!
bsxfun: 0.00002030 s.
repmat: 0.00005213 s.
cumsum: 0.00002180 s.
for : 0.00019560 s.
Where I used this for loop implementation:
base = [7 8 9 7 8 9];
A = zeros(1e3,length(base));
for n = 1:1e3;
A(n,:) = base+10*n;
end

For completeness, you could also obtain the desired result through the use of the repmat command:
n = 3;
a = [7 8 9 7 8 9];
addingMatrix = repmat([0:10:10*n+1]',1,size(a,2));
b = addingMatrix + repmat(a,n+1,1);
Result:
b =
7 8 9 7 8 9
17 18 19 17 18 19
27 28 29 27 28 29
37 38 39 37 38 39

Since repmat and bsxfun are already taken, another approach is to create a temporary array where [7 8 9 7 8 9] is the first row, followed by a matrix completely full of 10s where the number of rows is the desired number you want and the number of columns is the total number of elements in the base vector ([7 8 9 7 8 9]). You'd then apply a cumulative sum via cumsum along the rows:
n = 11; %// Number of rows - including the first row of [7 8 9 7 8 9]
base = [7 8 9 7 8 9];
A = [base; 10*ones(n-1, numel(base))];
B = cumsum(A, 1);
We get:
>> B
B =
7 8 9 7 8 9
17 18 19 17 18 19
27 28 29 27 28 29
37 38 39 37 38 39
47 48 49 47 48 49
57 58 59 57 58 59
67 68 69 67 68 69
77 78 79 77 78 79
87 88 89 87 88 89
97 98 99 97 98 99
107 108 109 107 108 109

Related

Insertion sort algorithm, weird behaviour

I am learning C programming and I'm currently on a classic one, the insertion sort algorithm.
For contextualization, I have a set of 3 arrays to test on :
the first one which is disordered
the second one is in a descending order
and the last one is is the ordered one but with a swap between 2 elements.
Here is my code :
int insertionSort(int* tab, int n){
int i;
for (i=1; i<n; i++){
int j = i;
while(tab[j] < tab[j-1]) {
swap(&tab[j-1], &tab[j]);
j-=1;
}
}
affiche(tab, n);
return 0;
}
For the 2 last arrays, it works fine.
But for the first one I got :
6 6 7 8 10 32521 14 15 17 19 20 21 23 25 26 28 28 28 32 32 34 35 38 38 39 43 44 46 48 49 50 58 59 62 64 65 69 71 75 79 79 79 81 84 86 89 92 93 97 99
instead of
3 6 6 7 8 10 14 15 17 19 20 21 23 25 26 28 28 28 32 32 34 35 38 38 39 43 44 46 48 49 50 58 59 62 64 65 69 71 75 79 79 79 81 84 86 89 92 93 97 99
As you can see, the algorithm works fine for a big part of the array, but for the sixth minimal values, I have random values (sometimes there are 92,93,97... for the first ones).
I don't have any core dump, which means that I am in the array's space in memory, but some values like 32521 let me think that my index j goes too far in memory.
Frankly, I don't see where the problem is.
Look at this loop
while(tab[j] < tab[j-1]) {
swap(&tab[j-1], &tab[j]);
j-=1;
}
j can run happily all over the place. There needs to be something that detects that j isnt < 0 (actually < 1 since you access 'tab[j-1]')
maybe
while((j >= 1) && (tab[j] < tab[j-1]) ) {
swap(&tab[j-1], &tab[j]);
j-=1;
}

Illegal instruction (core dumped) error: scanf in a while loop until EOF

So I wrote a function in C which gets input until EOF
while (scanf(" %c", &input) != EOF) {
// do stuff
}
I tried to use the following test:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
10 20 30 40 50 _66_ 15 66bb
As an input to the program. It actually runs the program but at the end it finishes with the following error: Illegal instruction (core dumped).
Other tests work fine, and after a quick check I found out that the problem begins after the last 50 (if I use only the numbers until 50 - it works fine). How to solve this problem?

Find a specific value in a specific row

I have a matrix A(97x13) ranging from 0 to 90
I would like to find in specific rows which values are lower than 45.
find(A(:,[4,7,10])<45);
My problem is that I don't know how to relate the resulting indices with the entire A matrix.
Can someone help me with that?
The result is in the form of a linear index. You can convert to row and column using ind2sub:
cols = [4,7,10];
ind = find(A(:,cols)<45);
[r, c] = ind2sub([size(A,1) numel(rows)], ind);
c = cols(c); %// change from "1,2,3" to "4,7,10"
To save some running time, you can use a "manual" version of ind2sub:
cols = [4,7,10];
ind = find(A(:,cols)<45);
r = mod(ind-1,size(A,1))+1;
c = cols(ceil(ind/size(A,1)));
Example:
A =
8 66 87 57 4 24 10 82 3 55
24 44 50 62 80 31 59 81 67 56
73 53 47 36 83 62 45 31 46 78
3 22 21 34 72 13 71 63 44 73
84 42 45 89 9 65 65 18 82 52
gives
r =
3
4
1
c =
4 4 7
Use ind2sub to get rows and columns, for example:
>> A=round(rand(5,3)*90)
A =
85 19 18
79 27 20
50 42 15
56 21 20
53 76 39
>> [I,J] = ind2sub(size(A), find(A(:,[1,3])<45))
I =
1
2
3
4
5
J =
2
2
2
2
2
>>

convert 1d to 2d matrix using zigzag ordering

I have an 1D matrix in MATLAB that in created with best answer of mentioned question below, I would like to reorder it to first array:
Matrix "Zigzag" Reordering
Source: Wikidpedia: Jpeg
m = [69 9 75 46 23 16 100 83 92 54 8 45];
zigzag_writing(m, 4, 3)
ans=
69 9 16 100
75 23 83 8
46 92 54 45
You can find the invzigzag at matlab file exchange.
>> invzigzag(m,3,4)
ans =
69 9 16 100
75 23 83 8
46 92 54 45

Find adjacent grid squares (user controls)

I've written some code in VB.net which creates three 10x10 grids of user controls and puts them on a windows form at run time, each user control is stored in a list.
I need to be able to find the grid squares adjacent to the current one, the problem I'm having is that the list is just from 1 to 100. It would be much simpler if I could say, store the user controls in an array(xposition, yposition) then I could just say the adjacent squares are xposition +-1 and yposition+-1, but I'm not sure how to do this.
Any help appreciated, thanks.
10x10 Grid layout of control indexes:
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
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
Const gridWidth=10
Dim idx = CtrlList.IndexOf(current control)
Dim leftIndex = If(idx Mod gridWidth > 0, idx - 1, idx)
Dim rightIndex = If(idx Mod gridWidth < gridWidth - 1, idx + 1, idx)
Dim upIndex = If(idx - gridWidth >= 0, idx - gridWidth, idx)
Dim downIndex = If(idx + gridWidth < CtrlList.Count - 1, idx + gridWidth, idx)
Try
Dim UserControlList As List(Of List(Of UserControl)).
Now as you load the user controls on to the form, put each row into a list then add that list to UserControlList.
Now you've got a 2 dimensional list, and UserControlList(3)(5) is the sixth(index 5) control on the fourth(index 3) line.
The adjacent controls will be UserControlList(2)(5),UserControlList(4)(5),UserControlList(3)(4), UserControlList(3)(6).

Resources