convert 1d to 2d matrix using zigzag ordering - arrays

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

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;
}

How to copy an array

I have defined an array like this:
uint8_t brightnessvariants[4][101]={{1,2,...},{3,4,...},{5,6,...},{7,8,...}};
Now for my application i have to fill another array with one of the 4 arrays:
uint8_t brightnesstable[] = brightnessvariants[index][];
But that doesn't work. Index is counted from 0 to 3.
brightnesstable and brightnessvariants are defined in a header file as extern
How can I do it right?
Simply do
uint8_t brightnesstable[101];
memcpy(brightnessstable, brightnessvariants[index], 101*sizeof(uint8_t));
brightnessvariants[index] is the address of the first item in the (index+1)nth row and the number of bytes you want to copy is
ROWSIZE*sizeof(ITEM_SIZE).
It really depends on what you need to do. If you need to create separate storage for a duplication of one of the rows of brightnessvariants, then you can simply declare a separate array and copy the values as discussed in the comments and the other answer.
If, however, you simply need to access one of the rows of brightnessvariants in the current scope, then there is no need for separate storage and copying. All that is required is to declare a pointer and assign the starting address of the desired row. Then you can access the desired row of brightnessvariants as if it were a separate array. e.g.
uint8_t brightnessvariants[4][101] = {{0}}, *btable = NULL;
Above, btable (short for your brightnesstable) is simply a uint8_t pointer. It can be assigned the the address of any of the rows in brightnessvariants. e.g. for the second row
btable = brightnessvariants[1];
btable can then be used to access any value within the second row, just as if it were a separate array. Here is a short example that may help:
#include <stdio.h>
#include <stdint.h>
int main (void) {
uint8_t brightnessvariants[4][101] = {{0}}, *btable = NULL;
int nrows = sizeof brightnessvariants / sizeof *brightnessvariants;
for (int i = 0; i < 101; i++) {
brightnessvariants[0][i] = i + 1;
brightnessvariants[1][i] = i + 3;
brightnessvariants[2][i] = i + 5;
brightnessvariants[3][i] = i + 7;
}
for (int i = 0; i < nrows; i++) {
printf ("\nbrightnesstable[%d] :\n\n", i);
btable = brightnessvariants[i];
for (int j = 0; j < 101; j++) {
if (j && j % 10 == 0) putchar ('\n');
printf (" %3hhu", btable[j]);
}
putchar ('\n');
}
return 0;
}
Example Use/Output
$ ./bin/ptrtobtable
brightnesstable[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 100
101
brightnesstable[1] :
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 100 101 102
103
brightnesstable[2] :
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 100 101 102 103 104
105
brightnesstable[3] :
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 100 101 102 103 104 105 106
107
Look things over and let me know if you have any questions. If you need an example of copying instead of the use of a pointer, let me know and I'm happy to help.

Replicating a vector while summing an increasing value

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

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
>>

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