put first array index at the end of array - c
I have an array called int arr[10] = {1,2,3,4,5}
From my understanding the rest of the array is filled with 0's.
My questions is if its a fixed array length how can I put the first index behind the last index that is not a 0. For example
I believe the 0 is not shown in real printf but I am including it for illustration purposes
for (int i = 0 ; i < 10 ; i++)
{
print("%i" , arr[i]);
}
The output
1 2 3 4 5 0 0 0 0 0
If i move the first index to the back of the 5 like so
for (int i = -1 ; i < 10 ; i++)
{
arr[i] = arr[i + 1];
print("%i" , arr[i]);
}
Will the output put the 1 behind the 5 or at the back of the whole array?
2 3 4 5 1 0 0 0 0 0
or because there is 0s then
2 3 4 5 0 0 0 0 0 1
If my question is unclear please tell me and I will try explain it.
The output
1 2 3 4 5 0 0 0 0 0
No, the actual output is
1234500000
Your code has undefined behavior. The first iteration of the loop (with i = -1) tries to assign to arr[-1], which does not exist:
arr[i] = arr[i + 1];
Similarly, the last iteration (with i = 9) tries to read from arr[10], which also does not exist.
I'm not sure why you think your code will move the first element back.
From my understanding the rest of the array is filled with 0's
You are right.:)
If i move the first index to the back of the 5 like so
for (int i = -1 ; i < 10 ; i++)
{
arr[i] = arr[i + 1];
print("%i" , arr[i]);
}
then you will get undefined behavior because the indices -1 and 10 are not valid indices.
It seems what you are trying to do is the following
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 10 };
int a[N] = { 1, 2, 3, 4, 5 };
size_t pos = 0;
while ( pos < N && a[pos] != 0 ) ++pos;
if ( pos != N && !( pos < 3 ) )
{
int tmp = a[0];
pos -= 2;
memmove( a, a + 1, pos * sizeof( int ) );
a[pos] = tmp;
}
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
return 0;
}
The program output is
2 3 4 1 5 0 0 0 0 0
Related
Implementing 8-Connectivity Hoshen-Kopelman Algorithm in C
I found here an implementation for Hoshen-Kopelman Algorithm, But it checks neighbors only up and left, meaning that a diagonal connection is not considered a connection. How can I improve this code so that even a diagonal connection will be considered a connection? In the following example I expect 1 object and not 7 objects: 4 5 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 0 --input-- 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 0 --output-- 1 0 2 0 3 0 4 0 5 0 6 0 7 0 0 0 0 7 0 0 HK reports 7 clusters found This is the implementation (full code can be found here): #include <stdio.h> #include <stdlib.h> #include <assert.h> /* Implementation of Union-Find Algorithm */ /* The 'labels' array has the meaning that labels[x] is an alias for the label x; by following this chain until x == labels[x], you can find the canonical name of an equivalence class. The labels start at one; labels[0] is a special value indicating the highest label already used. */ int* labels; int n_labels = 0; /* length of the labels array */ /* uf_find returns the canonical label for the equivalence class containing x */ int uf_find(int x) { int y = x; while (labels[y] != y) y = labels[y]; while (labels[x] != x) { int z = labels[x]; labels[x] = y; x = z; } return y; } /* uf_union joins two equivalence classes and returns the canonical label of the resulting class. */ int uf_union(int x, int y) { return labels[uf_find(x)] = uf_find(y); } /* uf_make_set creates a new equivalence class and returns its label */ int uf_make_set(void) { labels[0] ++; assert(labels[0] < n_labels); labels[labels[0]] = labels[0]; return labels[0]; } /* uf_intitialize sets up the data structures needed by the union-find implementation. */ void uf_initialize(int max_labels) { n_labels = max_labels; labels = calloc(sizeof(int), n_labels); labels[0] = 0; } /* uf_done frees the memory used by the union-find data structures */ void uf_done(void) { n_labels = 0; free(labels); labels = 0; } /* End Union-Find implementation */ #define max(a,b) (a>b?a:b) #define min(a,b) (a>b?b:a) /* print_matrix prints out a matrix that is set up in the "pointer to pointers" scheme (aka, an array of arrays); this is incompatible with C's usual representation of 2D arrays, but allows for 2D arrays with dimensions determined at run-time */ void print_matrix(int** matrix, int m, int n) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) printf("%3d ", matrix[i][j]); printf("\n"); } } /* Label the clusters in "matrix". Return the total number of clusters found. */ int hoshen_kopelman(int** matrix, int m, int n) { uf_initialize(m * n / 2); /* scan the matrix */ for (int y = 0; y < m; y++) { for (int x = 0; x < n; x++) { if (matrix[y][x]) { // if occupied ... int up = (y == 0 ? 0 : matrix[y - 1][x]); // look up int left = (x == 0 ? 0 : matrix[y][x - 1]); // look left switch (!!up + !!left) { case 0: matrix[y][x] = uf_make_set(); // a new cluster break; case 1: // part of an existing cluster matrix[y][x] = max(up, left); // whichever is nonzero is labelled break; case 2: // this site binds two clusters matrix[y][x] = uf_union(up, left); break; } } } } /* apply the relabeling to the matrix */ /* This is a little bit sneaky.. we create a mapping from the canonical labels determined by union/find into a new set of canonical labels, which are guaranteed to be sequential. */ int* new_labels = calloc(sizeof(int), n_labels); // allocate array, initialized to zero for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) if (matrix[i][j]) { int x = uf_find(matrix[i][j]); if (new_labels[x] == 0) { new_labels[0]++; new_labels[x] = new_labels[0]; } matrix[i][j] = new_labels[x]; } int total_clusters = new_labels[0]; free(new_labels); uf_done(); return total_clusters; } /* This procedure checks to see that any occupied neighbors of an occupied site have the same label. */ void check_labelling(int** matrix, int m, int n) { int N, S, E, W; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) if (matrix[i][j]) { N = (i == 0 ? 0 : matrix[i - 1][j]); S = (i == m - 1 ? 0 : matrix[i + 1][j]); E = (j == n - 1 ? 0 : matrix[i][j + 1]); W = (j == 0 ? 0 : matrix[i][j - 1]); assert(N == 0 || matrix[i][j] == N); assert(S == 0 || matrix[i][j] == S); assert(E == 0 || matrix[i][j] == E); assert(W == 0 || matrix[i][j] == W); } } /* The sample program reads in a matrix from standard input, runs the HK algorithm on it, and prints out the results. The form of the input is two integers giving the dimensions of the matrix, followed by the matrix elements (with data separated by whitespace). a sample input file is the following: 8 8 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 1 0 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 this sample input gives the following output: --input-- 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 1 0 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 1 --output-- 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 2 0 0 0 0 2 0 1 2 0 0 2 0 2 0 1 2 0 0 2 0 2 0 1 2 0 0 2 2 2 0 1 2 2 2 2 0 0 0 1 0 0 0 2 2 2 0 1 HK reports 2 clusters found */ int main(int argc, char** argv) { int m, n; int** matrix; /* Read in the matrix from standard input The whitespace-deliminated matrix input is preceeded by the number of rows and number of columns */ while (2 == scanf_s("%d %d", &m, &n)) { // m = rows, n = columns matrix = (int**)calloc(m, sizeof(int*)); for (int i = 0; i < m; i++) { matrix[i] = (int*)calloc(n, sizeof(int)); for (int j = 0; j < n; j++) scanf_s("%d", &(matrix[i][j])); } printf_s(" --input-- \n"); print_matrix(matrix, m, n); printf(" --output-- \n"); /* Process the matrix */ int clusters = hoshen_kopelman(matrix, m, n); /* Output the result */ print_matrix(matrix, m, n); check_labelling(matrix, m, n); printf("HK reports %d clusters found\n", clusters); for (int i = 0; i < m; i++) free(matrix[i]); free(matrix); } return 0; } I tried to change the function hoshen_kopelman as described below, but I still get 2 objects instead of 1: int hoshen_kopelman(int** matrix, int m, int n) { uf_initialize(m * n / 2); /* scan the matrix */ for (int y = 0; y < m; y++) { for (int x = 0; x < n; x++) { if (matrix[y][x]) { // if occupied ... int up = (y == 0 ? 0 : matrix[y - 1][x]); // look up int left = (x == 0 ? 0 : matrix[y][x - 1]); // look left // ----------- THE NEW CODE ------------- if (x > 0) { if (up == 0 && y > 0) // left+up up = matrix[y - 1][x - 1]; if (left == 0 && y < m - 1) // left+down left = matrix[y + 1][x - 1]; } // ---------- END NEW CODE -------------- switch (!!up + !!left) { case 0: matrix[y][x] = uf_make_set(); // a new cluster break; case 1: // part of an existing cluster matrix[y][x] = max(up, left); // whichever is nonzero is labelled break; case 2: // this site binds two clusters matrix[y][x] = uf_union(up, left); break; } } } } /* apply the relabeling to the matrix */ /* This is a little bit sneaky.. we create a mapping from the canonical labels determined by union/find into a new set of canonical labels, which are guaranteed to be sequential. */ int* new_labels = calloc(sizeof(int), n_labels); // allocate array, initialized to zero for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) if (matrix[i][j]) { int x = uf_find(matrix[i][j]); if (new_labels[x] == 0) { new_labels[0]++; new_labels[x] = new_labels[0]; } matrix[i][j] = new_labels[x]; } int total_clusters = new_labels[0]; free(new_labels); uf_done(); return total_clusters; } The following output is now obtained (I am expecting 1 and got 2): 4 5 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 0 --input-- 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 0 --output-- 1 0 1 0 1 0 1 0 1 0 2 0 1 0 0 0 0 1 0 0 HK reports 2 clusters found What is the correct way to correct the code to check all 8 neighbors?
I led you astray saying to check down-left. The algorithm relies on the current node it is examining being after all the neighbors it checks. So you need to check left, up, up-left, and up-right. You can use this in place of your new code: if (y > 0) { if (left == 0 && x > 0) // left+up left = matrix[y - 1][x - 1]; if (up == 0 && x < n-1) // right+up up = matrix[y - 1][x + 1]; }
Loop through a nested loop two-by two in C
I would like to loop through two arrays in a semi-zipped fashion, such that for as many entries as possible, the following pattern is observed: arr1[i] arr2[j] arr1[i] arr2[j+1] arr1[i+1] arr2[j+2] arr1[i+1] arr2[j+3] .... For example, if len arr1 is 96 and len arr2 is 3, I would like to see 0 0 0 1 1 2 1 0 2 1 2 2 3 0 3 1 4 2 4 0 5 1 5 2 I'm having a little trouble getting the logic exactly right; any help would be greatly appreciated
Pseudocode: i = 0; for (x = 0; i < arr1.len; ++x) { i = x / 2; // integer division j = x % arr2.len; // use arr1[i] and arr2[j] } Use integer division to repeat a value multiple times before moving on to the next value (e.g. 0 0 1 1 2 2 3 3 ...), where the number of times you want to repeat a value is equal to the denominator. Use modulo division to repeat a sequence of values indefinitely (e.g. 0 1 2 0 1 2 0 1 2 ...), where the number of items in the sequence is equal to the denominator.
If I have understood you correctly you need a loop like the one shown in the demonstrative program below. #include <stdio.h> #define N 10 #define M 3 int main( void ) { int a[N]; int b[N]; for ( int i = 0; i < N; i++ ) a[i] = i; for ( int i = 0; i < M; i++ ) b[i] = i; for (int i = 0, j = 0, k = 1; i < N; i += k ^= 1, j = ( j + 1 ) % M) { printf( "%d %d\n", a[i] , b[j] ); } } The program output is 0 0 0 1 1 2 1 0 2 1 2 2 3 0 3 1 4 2 4 0 5 1 5 2 6 0 6 1 7 2 7 0 8 1 8 2 9 0 9 1
Program that sums things to an array
This book requires me to answer '' What output do you expect from the following program?'' After reading it many times I dont seem to fully understand its inner workings. From what I get: First For loop stablishes that this process is going to repeat for 10 times. Variable j is assigned to start at 0. Second for loop starts the variable i at 0 and stablishes the condition i < j and does the operations written after it. What is going on exactly? j starts at 0 and so does i, therefore numbers[j] += numbers[i] equals 2? What happens after this operation is completed? If i and j equal to 0 then why is this condition i < j True? int main (void) { int numbers[10] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int i, j; for ( j = 0; j < 10; ++j ) for ( i = 0; i < j; ++i ) numbers[j] += numbers[i]; for ( j = 0; j < 10; ++j ) printf ("%i ", numbers[j]); printf ("\n"); return 0; }
The first thing you have to notice is that you have the outer loop, which runs from 0 to 10 and you to something to numbers[j]. This indicates that you take each element and modify it somehow. In order to find how, by inspecting the second loop and the right hand side of the assignment, you can notice that it adds to numbers[j] all elements with indices smaller than j. Now let's see what happens in a few steps: j = 0 : 1 0 0 0 0 0 0 0 0 0 j = 1 : 1 1 0 0 0 0 0 0 0 0 j = 2 : 1 1 2 0 0 0 0 0 0 0 j = 3 : 1 1 2 4 0 0 0 0 0 0 j = 4 : 1 1 2 4 8 0 0 0 0 0 At the end, you will get an array with the property that each element a[j] is equal to a[0] + a[1] + ... + a[j] and a[0] = 1. Now, taking a closer look at the beginning of the process, you have j = 0 and i = 0. The second for loop runs for as long as i < j. Since this comparison is false, the loop is not executed and we go to the next iteration of the outer loop, with j = 1.
Pass 2D array by reference
I want to be able to pass a 2D array to a function, and have it directly change the array in main, so pass by reference. When I try to compile, I get error: expected expression before { in the switch cases. (boardSize=10, but that is not known at compilation time) void fillBoard(int **, int); int main() { int **board = malloc(sizeof(int *) * boardSize); fillBoard(board, boardSize); } void fillBoard(int **board) { int i, *row = malloc(sizeof(int) * boardSize); for (i=0; i<boardSize; i++) { board[i] = malloc(sizeof(int) * boardSize); switch(i) { case 1: row = {1,0,1,0,1,1,0,0,1,0}; break; default: row = {0,0,0,0,0,0,0,0,0,0}; break; } board[i] = row; } }
There a many different ways to do this. The key is to keep track of what you are addressing where. You can use a single or double pointer to pass and fill board, it all depends on how you want to keep track of the elements. (while the 2-dimensional array, provides a convenience in referencing elements, all values are sequential in memory, and can be accessed with a 1-dimensional reference and offset). There is one important suggestion when allocating memory for numeric arrays. You must always initialize all elements of the array to protect against attempting to access or dereference an uninitialized value (Undefined behavior). The simple way to do this is to allocate with calloc instead of malloc. calloc allocates and initializes all values to zero (NULL). Also be aware of the need to track the memory you allocate over the life of your program and free the memory when you no longer need it. This will prevent memory leaks from developing. In a short bit of code like the following, the memory is freed when the program exits. If this were part of some larger code, you would need to free board and board2 when there data was no longer needed. An example using your original array would be: #include <stdio.h> #include <stdlib.h> #define boardSize 10 void fillBoard_p (int *a); void fillBoard_p2p (int **a); int main() { int i = 0; int j = 0; /* declaring board as an integer pointer */ int *board = calloc (boardSize * boardSize, sizeof (*board)); /* declaring board as a pointer to pointer */ int **board2 = calloc (boardSize, sizeof (*board2)); for (i = 0; i < boardSize; i++) { board2[i] = calloc (boardSize, sizeof (**board2)); } fillBoard_p (board); fillBoard_p2p (board2); printf ("\nboard as an integer pointer:\n"); for (i = 0; i < boardSize * boardSize; i++) { if (i % boardSize == 0) printf ("\n %d", board[i]); else printf (" %d", board[i]); } printf ("\n"); printf ("\nboard2 as an pointer to integer pointer:\n\n"); for (i = 0; i < boardSize; i++) { for (j = 0; j < boardSize; j++) { printf (" %d", board2[i][j]); } printf ("\n"); } printf ("\n"); return 0; } void fillBoard_p(int *a) { // 0=WHITE, 1=BLACK int i = 0; int j = 0; int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0}, {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; for (i = 0; i < boardSize; i++) for (j = 0; j < boardSize; j++) a[i*boardSize+j] = b[i][j]; } void fillBoard_p2p (int **a) { // 0=WHITE, 1=BLACK int i = 0; int j = 0; int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0}, {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; for (i = 0; i < boardSize; i++) for (j = 0; j < boardSize; j++) a[i][j] = b[i][j]; } output: $ ./bin/fillboard board as an integer pointer: 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 0 0 1 1 0 0 0 1 board2 as an pointer to integer pointer: 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 0 0 1 1 0 0 0 1 Additionally, since a 2-D array is stored sequentially in memory, you can take advantage of that fact and make use of memcpy (in string.h) to fill the array passed to your function. This can reduce your function to: void fillBoard_mc (int *a) { // 0=WHITE, 1=BLACK int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0}, {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; memcpy (a, b, boardSize * boardSize * sizeof (int)); } Were it not for the particularity of the compiler and pointer decay, you could simply use a statically declared array, such as: int board[boardSize][boardSize] = {{0}}; passing the address of the array to your function (becoming a 3-star programmer): fillBoard (&board); with a function similar to: void fillBoard (int *a[][boardSize]) { // 0=WHITE, 1=BLACK int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0},A {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; memcpy (a, b, boardSize * boardSize * sizeof (int)); } Due to pointer decay (board[10][10] => board[*][10]), you will receive an incompatible pointer type warning, despite the function successfully copying the memory as intended. Code that does not compile without warning, should not be relied on in practice.
Storing subsets of a array
this program is "calculating" all subsets of the array source. I need to store the resulting values in another 2D filed named polje. If I just use the printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); the code works fine but something fails when it is trying to copy everything into the resulting field. I suppose I am dogin something wrong in the indexing of the array polje. #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int f; int i,j; int source[2][3] = {{0,3,5},{3,4,2}}; int currentSubset = 3; int polje[8][3]; for(i=0;i<8;i++){ for(j=0;j<3;j++){ polje[i][j]=0; }} int tmp; while(currentSubset) { tmp = currentSubset; for( i = 0; i<3; i++) { if (tmp & 1) { printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); //writes out everything I want polje[currentSubset][0]=source[i][0]; polje[currentSubset][1]=source[i][1]; polje[currentSubset][2]=source[i][2]; } tmp >>= 1; } printf("\n"); currentSubset--; } for(i=0;i<8;i++){ for(j=0;j<3;j++){ printf("%d ", polje[i][j]); }printf("\n");} return (EXIT_SUCCESS); } The output field should be: 0 3 5 3 4 2 3 4 2 0 0 0 0 3 5 0 0 0 0 0 0 0 0 0 But instead it is: 0 3 5 3 4 2 3 4 2 0 0 0 *0 0 0* 0 0 0 0 0 0 0 0 0
tmp is a bit mask with only two bits, so the inner loop should be for ( i = 0; i < 2; i++ ). Also the correct index into the polje array is polje[currentSubset * 2 + i][0] since each subset in polje takes two spaces and i is either 0 or 1.
I think you just have a logic error. Your loop's skeleton is: currentSubset = 3; while ( currentSubset ) { // ... polje[currentSubset][...] = ...; // ... currentSubset--; } So you never write to any rows except the first three.