Find adjacent grid squares (user controls) - arrays

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

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

Output in read file and sort integers leaves a white space I can't find

My code takes in a text document argument and sorts the integers but when I run testing, it fails a simple white space at the end instead of a \n but I figure out how to stop the final number in the array with a new line instead of a space. Here is the code:
/* display values */
for (i = 0; i < count; i++ ) {
printf ("%ld ", sorted[i]);
}
Here is the test result and the issue:
Program Output
1: 1 2 3 4 5 5 7 8 9 9 9 10 10 11 11 12 14 17 18 20 20 20 24 24 25 25 26 26 27 27 28 28 29 30 30 30 30 31 33 35 35 36 38 40 40 41 42 42 42 47 47 47 48 48 48 48 50 50 51 52 52 52 54 54 57 57 57 57 57 60 61 61 62 62 62 63 64 66 66 66 67 67 69 70 72 72 73 73 75 77 80 82 83 83 83 84 85 86 87 88 88 88 89 91 92 93 94 94 96 97 97 99 [blank space]
Expected Program Output
1: 1 2 3 4 5 5 7 8 9 9 9 10 10 11 11 12 14 17 18 20 20 20 24 24 25 25 26 26 27 27 28 28 29 30 30 30 30 31 33 35 35 36 38 40 40 41 42 42 42 47 47 47 48 48 48 48 50 50 51 52 52 52 54 54 57 57 57 57 57 60 61 61 62 62 62 63 64 66 66 66 67 67 69 70 72 72 73 73 75 77 80 82 83 83 83 84 85 86 87 88 88 88 89 91 92 93 94 94 96 97 97 99
2: [new line]
I tried putting in a \n in printf ("%ld ", sorted[i]); after sorted[i] but it needs to go at the close of the array and I'm not certain how (or where) to add it with cause more issues.
/* display values */
for (i = 0; i < count; i++ ) {
printf ("%ld ", sorted[i]);
}
This outputs a space after each number. If that's not what you want, don't do it. Maybe you want this:
/* display values */
if (count > 0)
printf ("%ld", sorted[0]);
for (i = 1; i < count; i++ ) {
printf (" %ld", sorted[i]); // space before every number but first
}
If one doesn't want to duplicate code.
#include <stdio.h>
int main(void) {
const size_t count = 100;
size_t i;
/* display values */
for (i = 0; i < count; i++ ) {
printf ("%s%ld", i ? " " : "", i + 1 /*sorted[i]*/ );
}
fputc('\n', stdout);
return 0;
}
I expect it to be slower, but I think the intent of the code is clearer.

Printing from 1 to 100 in columns

Code:
for(int i = 1; i <= 100; i++){
if(i % 10 == 1)
printf("\n%d", i);
else printf("%4d",i);
}
Results:
(blank line)
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
How can I remove the first blank line without doing something like:
for(int i = 1; i <= 100; i++){
if(i == 1 || i % 10 == 1)
printf("\n%d", i);
else printf("%4d",i);
}
And how can I 'indent' the columns? As the last column isn't properly arranged, and I have no idea how to fix it using printf's.
At last, sorry for wrinting '(blank line)' as I don't know how to make a blank line, and thanks for the help.
Rather than printing a newline at the start of a line, print it at the end instead:
for (int i = 1; i <= 100; i++){
printf("%4d",i);
if (i % 10 == 0)
printf("\n");
}
This prints each number in a 4 character field, then prints a newline if the last number is divisible by 10.
Output:
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
The style is strange, a newline doesn't belong at the start of a string literal. A printf call should print the line and then output a newline if necessary:
"\nBad style"
"Good style\n"
To print the values correctly, change the logic. Always print the values of i, and then check if i is divisible by 10, and print the newline if it is.
for(int i = 1; i <= 100; i++)
printf("%*d%c", (i % 10 == 1)? 0 : (i == 2) ? 4 : 3, i, (i % 10) ? ' ' : '\n');
I have always done something like this:
#include <stdio.h>
int main (void) {
for (int i = 0; i < 100; i++) {
if (i && i % 10 == 0) putchar ('\n');
printf ("%4d", i + 1);
}
putchar ('\n');
return 0;
}
You can also you separate format strings to accomplish the same thing:
char *fmt = "%4d",
*fmtn = "%4d\n";
for (int i = 0; i < 100; i++)
printf ((i+1) % 10 == 0 ? fmtn : fmt, i + 1);
putchar ('\n');
(note: in both cases the loop is indexed from 0 to accommodate indexing arrays)
Example Use/Output
$ ./bin/arraycols
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

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.

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

Resources