How do I return the indices of a multidimensional array element in C? - c

Say I have a 2D array of random boolean ones and zeroes called 'lattice', and I have a 1D array called 'list' which lists the addresses of all the zeroes in the 2D array. This is how the arrays are defined:
define n 100
bool lattice[n][n];
bool *list[n*n];
After filling the lattice with ones and zeroes, I store the addresses of the zeroes in list:
for(j = 0; j < n; j++)
{
for(i = 0; i < n; i++)
{
if(!lattice[i][j]) // if element = 0
{
list[site_num] = &lattice[i][j]; // store address of zero
site_num++;
}
}
}
How do I extract the x,y coordinates of each zero in the array? In other words, is there a way to return the indices of an array element through referring to its address?
EDIT: I need to make the code as efficient as possible, as I'm doing lots of other complicated stuff with much larger arrays. So a fast way of accomplishing this would be great

One solution is to map (x, y) to a natural number (say z).
z = N * x + y
x = z / N (integer division)
y = z % N
In this case, you should use int list[N * N];
Another solution is to just store the coordinates when you find a zero, something like:
list_x[site_num] = x;
list_y[site_num] = y;
site_num++;
Or you can define a struct of two ints.

Well, it is possible with some pointer arithmetic.
You have the address of your first element of lattice and the addresses of all zero-fields in list. You know the size of bool. By subtracting the first-elements address from a zero-field address and dividing by the size of bool you get a linar index. This linear index can be calculated into the 2-dim index by using modulo and division.
But why don't you store the 2-dim index within your list instead of the address? Do you need the addess or just the index?
And you should think about turning the for-loops around (outer loop i, inner loop j).

struct ListCoords
{
int x, y;
} coords[n*n];
for(i = 0; i < site_num; i++)
{
int index = list[i] - &lattice[0][0];
coords[i].x = index % n;
coords[i].y = index / n;
}
I may have the % and / operators backwards for your needs, but this should give you the idea.

How do I extract the x,y coordinates of each zero in the array? In other words, is there a way to return the indices of an array element through referring to its address?
You can't. Simple as that. If you need that information you need to pass it along with the arrays in question.
bool *list[n*n]; is an illegal statement in C89 (EDIT: Unless you made n a macro (yuck!)), you may wish to note that variable length arrays are a C99 feature.

Related

Find the indices of the k smallest values in C

I'm implementing K Nearest Neighbor in C and I've gotten to the point where I've computed a distance matrix of every point in my to-be-labeled set of size m to every point in my already-labeled set of size n. The format of this matrix is
[[dist_0,0 ... dist_0,n-1]
.
.
.
[dist_m-1,0 ... dist_m-1,n-1]]
Next, I need to find the k smallest distances in each row so I can use the column indices to access the labels of those points and then compute the label for the point the row index is referring to. The latter part is trivial but computing the indices of the k smallest distances has me stumped. Python has easy ways to do something like this but the bare bones nature of C has gotten me a bit frustrated. I'd appreciate some pointers (no pun intended) on what to go about doing and any helpful functions C might have to help.
Without knowing k, and assuming that it can be variable, the simplest way to do this would be to:
Organize each element in a structure which holds the original column index.
Sort each row of the matrix in ascending order and take the first k elements of that row.
struct item {
unsigned value;
size_t index;
};
int compare_items(void *a, void *b) {
struct item *item_a = a;
struct item *item_b = b;
if (item_a->value < item_b->value)
return -1;
if (item_a->value > item_b->value)
return 1;
return 0;
}
// Your matrix:
struct item matrix[N][M];
/* Populate the matrix... make sure that each index is set,
* e.g. matrix[0][0] has index = 0.
*/
size_t i, j;
for (i = 0; i < M; i++) {
qsort(matrix[i], N, sizeof(struct item), compare_items);
/* Now the i-th row is sorted and you can take a look
* at the first k elements of the row.
*/
for (j = 0; j < k; j++) {
// Do something with matrix[i][j].index ...
}
}

Applying a function on sorted array

Taken from the google interview question here
Suppose that you have a sorted array of integers (positive or negative). You want to apply a function of the form f(x) = a * x^2 + b * x + c to each element x of the array such that the resulting array is still sorted. Implement this in Java or C++. The input are the initial sorted array and the function parameters (a, b and c).
Do you think we can do it in-place with less than O(n log(n)) time where n is the array size (e.g. apply a function to each element of an array, after that sort the array)?
I think this can be done in linear time. Because the function is quadratic it will form a parabola, ie the values decrease (assuming a positive value for 'a') down to some minimum point and then after that will increase. So the algorithm should iterate over the sorted values until we reach/pass the minimum point of the function (which can be determined by a simple differentiation) and then for each value after the minimum it should just walk backward through the earlier values looking for the correct place to insert that value. Using a linked list would allow items to be moved around in-place.
The quadratic transform can cause part of the values to "fold" over the others. You will have to reverse their order, which can easily be done in-place, but then you will need to merge the two sequences.
In-place merge in linear time is possible, but this is a difficult process, normally out of the scope of an interview question (unless for a Teacher's position in Algorithmics).
Have a look at this solution: http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f04/Artikler/04/Huang88.pdf
I guess that the main idea is to reserve a part of the array where you allow swaps that scramble the data it contains. You use it to perform partial merges on the rest of the array and in the end you sort back the data. (The merging buffer must be small enough that it doesn't take more than O(N) to sort it.)
If a is > 0, then a minimum occurs at x = -b/(2a), and values will be copied to the output array in forward order from [0] to [n-1]. If a < 0, then a maximum occurs at x = -b/(2a) and values will be copied to the output array in reverse order from [n-1] to [0]. (If a == 0, then if b > 0, do a forward copy, if b < 0, do a reverse copy, If a == b == 0, nothing needs to be done). I think the sorted array can be binary searched for the closest value to -b/(2a) in O(log2(n)) (otherwise it's O(n)). Then this value is copied to the output array and the values before (decrementing index or pointer) and after (incrementing index or pointer) are merged into the output array, taking O(n) time.
static void sortArray(int arr[], int n, int A, int B, int C)
{
// Apply equation on all elements
for (int i = 0; i < n; i++)
arr[i] = A*arr[i]*arr[i] + B*arr[i] + C;
// Find maximum element in resultant array
int index=-1;
int maximum = -999999;
for (int i = 0; i< n; i++)
{
if (maximum < arr[i])
{
index = i;
maximum = arr[i];
}
}
// Use maximum element as a break point
// and merge both subarrays usin simple
// merge function of merge sort
int i = 0, j = n-1;
int[] new_arr = new int[n];
int k = 0;
while (i < index && j > index)
{
if (arr[i] < arr[j])
new_arr[k++] = arr[i++];
else
new_arr[k++] = arr[j--];
}
// Merge remaining elements
while (i < index)
new_arr[k++] = arr[i++];
while (j > index)
new_arr[k++] = arr[j--];
new_arr[n-1] = maximum;
// Modify original array
for (int p = 0; p < n ; p++)
arr[p] = new_arr[p];
}

Array of pointers in C

How do I create a array containing multiple pointers in C?
e.g. If you have a data-set of size n which you want to split into t chunks. So if you want to access an element in the range 0-(n/t) , you would need to access the array index and go to the corresponding pointer index.
This will work for int data
int *arr_of_ptr[t];
for(int i = 0; i < t; i++)
arr_of_ptr[i] = malloc(sizeof(int) * n/t);
So you want to store n elements in t arrays.
First note that n modulo t may not be 0. So you can't simply store n/t elements in the t arrays.
You'll want to store m = n / (t-1) elements in the t-1 first arrays and the rest in the last array.
int i, m;
// Create an array of t arrays that will contain the value of type T
T **arrays = malloc(t*sizeof(T*));
// Compute the maximum number of elements in each array
m = n / (t-1);
// Create the t arrays
for (i = 0; i < t; ++i)
arrays[i] = malloc(m*sizeof(T));
To access the element k in this data structure, you have to determine the index i of the array holding the data, and the index j of the element in the array. The index i is i = k/m, and the index j is j = k%m (k modulo m).
The following expression thus gives you access to the element k of the n elements.
arrays[k/m][k%m]

Best solution to represent Data[i,j] in c?

There is a pseudocode that I want to implement in C. But I am in doubt on how to implement a part of it. The psuedocode is:
for every pair of states qi, and qj, i<j, do
D[i,j] := 0
S[i,j] := notzero
end for
i and j, in qi and qj are subscripts.
how do I represent D[i,J] or S[i,j]. which data structure to use so that its simple and fast.
You can use something like
int length= 10;
int i =0, j= 0;
int res1[10][10] = {0, }; //index is based on "length" value
int res2[10][10] = {0, }; //index is based on "length" value
and then
for (i =0; i < length; i++)
{
for (j =0; j < length; j++)
{
res1[i][j] = 0;
res2[i][j] = 1;//notzero
}
}
Here D[i,j] and S[i,j] are represented by res1[10][10] and res2[10][10], respectively. These are called two-dimentional array.
I guess struct will be your friend here depending on what you actually want to work with.
Struct would be fine if, say, pair of states creates some kind of entity.
Otherwise You could use two-dimensional array.
After accept answer.
Depending on coding goals and platform, to get "simple and fast" using a pointer to pointer to a number may be faster then a 2-D array in C.
// 2-D array
double x[MAX_ROW][MAX_COL];
// Code computes the address in `x`, often involving a i*MAX_COL, if not in a loop.
// Slower when multiplication is expensive and random array access occurs.
x[i][j] = f();
// pointer to pointer of double
double **y = calloc(MAX_ROW, sizeof *y);
for (i=0; i<MAX_ROW; i++) y[i] = calloc(MAX_COL, sizeof *(y[i]));
// Code computes the address in `y` by a lookup of y[i]
y[i][j] = f();
Flexibility
The first data type is easy print(x), when the array size is fixed, but becomes challenging otherwise.
The 2nd data type is easy print(y, rows, columns), when the array size is variable and of course works well with fixed.
The 2nd data type also row swapping simply by swapping pointers.
So if code is using a fixed array size, use double x[MAX_ROW][MAX_COL], otherwise recommend double **y. YMMV

How do you dynamically allocate a contiguous 3D array in C?

In C, I want to loop through an array in this order
for(int z = 0; z < NZ; z++)
for(int x = 0; x < NX; x++)
for(int y = 0; y < NY; y++)
3Darray[x][y][z] = 100;
How do I create this array in such a way that 3Darray[0][1][0] comes right before 3Darray[0][2][0] in memory?
I can get an initialization to work that gives me "z-major" ordering, but I really want a y-major ordering for this 3d array
This is the code I have been trying to use:
char *space;
char ***Arr3D;
int y, z;
ptrdiff_t diff;
space = malloc(X_DIM * Y_DIM * Z_DIM * sizeof(char))
Arr3D = malloc(Z_DIM * sizeof(char **));
for (z = 0; z < Z_DIM; z++)
{
Arr3D[z] = malloc(Y_DIM * sizeof(char *));
for (y = 0; y < Y_DIM; y++)
{
Arr3D[z][y] = space + (z*(X_DIM * Y_DIM) + y*X_DIM);
}
}
You can't change the array ordering implicit in the language. The array ordering is standard in C.
If you want to change the way your ordering occurs, just change how you access your array, ie: [x][z][y] instead of [x][y][z].
I think the only way to do this is to write your own wind/unwind functionality on a contiguous datastore. In other words you are going to have to write your own map to calculate the storage position of your values.
If you are trying to make a certain order traversal of your array more efficient, you could always transform the incoming matrix before you put it into the array and then do the transform again when you get it out. C style multi-dimensional arrays are packed order, so the math might get a bit tricky (and is beyond what I can detail out here in the time I have).
Sorry for not having a better answer, but I hope that helps
Using an array of pointers can speed things up, but at the cost of greater complexity. If you're not certain you need the performance, then you might try using a C macro:
#define ARR3D(x,y,z) space[(x) + XDIM*((y) + Y_DIM*(z))]
This assumes that x, y, and z are the innermost, middle, and outermost dimensions, respectively.
Pseudocode:
malloc a chunk of memory big enough for
the char *** pointer for z,
the char ** pointers for y, which will get pointed to by zs
the char * pointers for x, which will get pointed to by ys
the big block of data that they will, in the end, be pointed to by xs
assign z's, y's, x's so that
contiguous blocks from the big block of data are adjacent in the y dimension
(instead of adjacent in the x dimension, as would be normal)
I have done the single-malloc trick for 2D arrays, simply because of the mental exercise and the added convenience of a single malloc / single free, and it works beautifully (just make sure to get a well-aligned memory chunk). I never thought of using this to subvert memory adjacency.

Resources