I need to rotate a matrix and call the funcion without using [],
I can't even think on a solution.
void _90DegClockwise(int *pS, int row, int col) {
for (int i = 0; i < row; ++i)
{
for (int j = i + 1; j < col; j++) {
int temp;
temp = (int)(pS);
*((int*)((pS + i) + j)) = (int*)((pS + j) + i);
(int*)((pS + j) + i) = temp;
}
}
}
I don't know how to insert a value to matrix or how to swap
To solve this, you need to understand how arrays work in C.
Lets say you have a 3 * 3 matrix, that is declared like this:
int matrix[3][3];
While you imagine this to be a square like this:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
For the computer it is a consecutive "line" in memory looking like this:
+---+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+---+---+
^
|____matrix
And variable matrix holds the address of the first cell
So, if you want to access any cell without using the [] operator, you need to calculate the address of that cell.
Lets do this for the middle cell:
matrix[1][1];
This is the second cell of the second row, so you need to add the width of the first row to the start of the matrix, and then add one more cell from the start of the second row. And you want to derefernce the address to get to the value like so:
*(matrix + (3 * 1) + 1);
What if we wanted the middle cell of the third row? Same thing, but add width of two rows:
*(matrix + (3 * 2) + 1);
To sum up: if you want to access cell x in row y of the matrix you would calculate its address like this:
*(matrix + (with * y) + x);
You're mixing up the pointer and the dereferenced value in the 3 lines
In the first line temp = (int)(pS); you're assigning the pointer value to temp instead of the value that the pointer points to. Similarly you're also assigning the pointer value to the memory location like this *((int*)((pS + i) + j)) = (int*)((pS + j) + i); which makes no sense.
Then in the last line (int*)((pS + j) + i) = temp; doesn't work because you're assigning a value to an address instead of a memory location
Remember to use * to dereference a pointer to get the variable, i.e. the memory location the pointer points to. In C a[b] is equivalent to *(a + b) so just replace all those occurrences. I don't know why you do it "correctly" with *((int*)((pS + i) + j)) but didn't apply that to others
Even then you're calculating the index incorrectly. *((int*)((pS + i) + j)) is just pS[i + j] which is not the correct item you want. If you pass the 2D array as a 1D array you need to calculate the real index like this pS[i + j*width]
So to do
temp = pS[i + j*width];
pS[i + j*width] = pS[j + i*width];
pS[j + i*width] = temp;
just change it to
temp = *(pS + i + j*width);
*(pS + i + j*width) = *(pS + j + i*width);
*(pS + j + i*width) = temp;
You should enable all compiler warnings. They're very helpful and help you solve most of the above problem
Related
I'm trying to make a function that shuffles an image as shown below:
Its argument takes three 600x400 RGB arrays to create the pixel colors. I have been trying to brainstorm this for so many hours but I'm so confused about methods to do it. Here's an idea I've tried working out, but I got overwhelmed and stumped with:
Copy each RGB array (R[][], G[][], and B[][] separately which combined makes a colored image) into their respective temporary arrays. Split the temporary arrays into a 4x4. Each element would contain its own 2D array with a block of the original image. Then using the random library I can assign the elements to new locations within the 4x4. I have no idea how to do this without making 42 arrays (16 arrays per color in the 4x4, but 42 arrays for R, G, and B). I would appreciate any advice or Here is the code I currently have, but I paused (or possibly abandoned) working on:
void Shuffle(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]){
// Initialize 150x100 inner shuffle arrays. These arrays are chunks of the original image
int shuffArrR[150][100] = {0};
int shuffArrG[150][100] = {0};
int shuffArrB[150][100] = {0};
int row = 0, col = 0;
/*
BOUNDARY INFO FOR 4x4 ARRAY:
C1: C2: C3: C4: hBound# (row):
--------------------> 1
R1: | | | | |
--------------------> 2
R2: | | | | |
--------------------> 3
R3: | | | | |
--------------------> 4
R4: | | | | |
--------------------> 5
| | | | |
v v v v v
vBound# (col): 1 2 3 4 5
vBound: hBound:
#: col: #: row:
1 0 1 0
2 150 2 100
3 300 3 200
4 450 4 300
5 600 5 400
*/
// Define boundaries
int const vBound1 = 0, vBound2 = 150, vBound3 = 300, vBound4 = 450;
int const hBound1 = 0, hBound2 = 100, hBound3 = 200, hBound4 = 300;
for(row; row < HEIGHT; row++){
for(col; col < WIDTH; col++){
// Copy RGB arrays to shuffle arrays
shuffArrR[col][row] = R[col][row];
shuffArrG[col][row] = G[col][row];
shuffArrB[col][row] = B[col][row];
// Define 16 blocks in 4x4 array ------------------
// If in R1
if(row >= hBound1 && row <= hBound2){
// And in C1
if(col >= vBound1 && col <= vBound2){
// ** I stopped here after I realized how many arrays I'd have to make to account for every element in the 4x4 **
}
}
}
}
}
Use a better data structure
Right now, you are using multi-dimensional arrays, which has certain upsides and downsides lightly touched on elsewhere on SO. Because what you are doing is image processing, performance may be critical for you, and dereferencing multi-dimensional arrays is not exactly optimal for a variety of reasons (i.e. you're likelier to lose performance due to non-sequential reads).
There are a couple of ways to both improve performance, while also making your life easier:
Interleaved one-dimensional array
Meaning, you should use a single unsigned char img[WIDTH * HEIGHT * COLORS] array. This has the benefit of making your code also easier to maintain, as you can then handle RGB, B&W and RGBA images with a change to the constant COLORS. To access a given color of a single pixel, you could have img[y * width * COLORS + x * COLORS + color]. You could also write a macro to help with that, e.g.
#define INDEX_XYZ(x,y,color) ((y) * WIDTH * COLORS + (x) * COLORS + (color))
To further improve on the usability of the function, considering passing it the size of each dimension, along with the number of colors. For example, you could change the signature to be...
void Shuffle(unsigned char image[], int height, int width, int colors);
Which would allow you to use the same function on images of any size (as long as both dimensions are divisible by four) and any color. You might also want to pass an argument indicating the number of subdivisions, so you could have a 3-by-3 segmentation or 8-by-8 segmentation if you wanted, and without having to change the function or repeat the code.
Split the image into segments
One way to do this would be to create the arrays for the segments...
unsigned char segments[SEG_HORI * SEG_VERT][WIDTH / SEG_HORI * HEIGHT / SEG_VERT * COLOR];
Note the multidimensionality - it is fine here, as it is desirable for us to have a number of separate segment to store the data in.
After which we copy data from the original:
// Calculate the height/width for the segments; you could do this as a macro too.
int seg_height = HEIGHT / SEG_VERT;
int seg_width = WIDTH / SEG_HORI;
// Iterate through the rows in the picture
for (int y = 0; y < HEIGHT; y++)
{
// Obtain the Y-coordinate of the segment.
int segy = y / seg_height;
// Iterate through the columns in the picture
for (int x = 0; x < WIDTH; x++)
{
// Calculate the X-coordinate of the segment.
int segx = x / seg_width,
// Then calculate its index, using the X and Y coordinates.
seg = segy * SEG_HORI + segx,
// Then, calculate the source index (from the image).
src_idx = y * WIDTH * COLORS + x * COLORS,
// Then, map the coordinates to the segment; notice that we take
// modulos on the coordinates to get them to correctly map.
dst_idx = y % seg_height * seg_width * COLORS + x % seg_width * COLORS;
// Then copy the colors. You could also use memcpy(),
// but the below should be more educational.
for (int c = 0; c < COLORS; c++)
segments[seg][dst_idx + c] = img[src_idx + c];
}
}
Now, the image has been copied into the segments, and you can reorder them as you wish, as the "segments" are simply pointers. For example, the below would swap the top-left and the bottom-right segments.
unsigned char seg_temp[] = segments[0];
segments[0] = segments[15];
segments[15] = seg_temp;
Finally, to finalize the process and merge the segments back together, you need to redo the process above in reverse; it should be quite trivial to do, so I'll leave it for you as an exercise.
Final Notes
If you haven't already, you should familiarize yourself with the malloc() and free() functions, as well as memset() and memcpy(). They should prove very useful in the future, and would also improve the performance here as then you could copy everything into a destination array (along with the shuffle) in n operations, instead of modifying the original in 2n.
Disclaimer 1: I haven't ran any of the code through a compiler. No guarantees that it will work out of the box.
Disclaimer 2: I also do not claim the code to be well-optimized. Have to leave something for you to do.
Label each block with an ID, 0, 1, 2, ...15 .
-----------------
| 12| 13| 14| 15|
-----------------
| 8 | 9 | 10| 11|
-----------------
| 4 | 5 | 6 | 7 |
-----------------
| 0 | 1 | 2 | 3 |
-----------------
Put all ID in an array, then shuffle the array. shuffle like this. Then traversal the array and swap content of each block.
int arr[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
arr_shuffle(arr, 16);
int i;
for (i = 0; i < 16; i++) {
swap_block(i, arr[i]);
}
Now the problem will be how to swap two block. Let's say we have block A and block B. Both size should be 100(height) * 150(width). Then think A is an array like A[100][150], and B is B[100][150]. swap this array will be like below.
for (i = 0; i < 100; i++) {
for (j = 0; j < 150; j++) {
swap(A[i][j], B[i][j];
}
}
The final step should be convert A[i][j] and B[i][j] to the real element in array R/G/B. This can be done simply by math.
void get_real_id(int block_id, int x, int y, int *real_x, int *real_y)
{
int row, col;
row = block_id / 4; // convert block id to row number
col = block_id % 4; // convert block id to col number
// find BLOCK[y][x] in array R, which should be R[real_y][real_x]
*real_x = (col * (WIDTH/4)) + x;
*real_y = (row * (HEIGHT/4)) + y;
}
The sample code in below will work for array R. The define of R is R[HEIGHT][WEIGHT], not R[WEIGHT][HEIGHT] (This define should work too but I can't think with it).
int R[HEIGHT][WIDTH];
int arr_shuffle(int *arr, int len)
{
size_t i;
for (i = 0; i < len - 1; i++)
{
size_t j = i + rand() / (RAND_MAX / (len - i) + 1);
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
void get_real_id(int block_id, int x, int y, int *real_x, int *real_y)
{
int row, col;
row = block_id / 4;
col = block_id % 4;
*real_x = (col * (WIDTH/4)) + x;
*real_y = (row * (HEIGHT/4)) + y;
}
void swap_block(int src, int dst)
{
int w_len = WIDTH / 4; // should be 150
int h_len = HEIGHT / 4; // should be 100
int i, j;
for (i = 0; i < h_len; i++) {
for (j = 0; j < w_len; j++) {
int real_src_x;
int real_src_y;
int real_dst_x;
int real_dst_y;
get_real_id(src, j, i, &real_src_x, &real_src_y);
get_real_id(dst, j, i, &real_dst_x, &real_dst_y);
// swap two point.
int r = R[real_src_y][real_src_x];
R[real_src_y][real_src_x] = R[real_dst_y][real_dst_x];
R[real_dst_y][real_dst_x] = r;
}
}
}
int Shuffle()
{
int i;
int arr[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
arr_shuffle(arr, 16);
for (i = 0; i < 16; i++) {
int src_block_id = i;
int dst_block_id = arr[i];
swap_block(src_block_id, dst_block_id);
}
}
I should mention there is chance that after the Shuffle nothing changes.
Array A contains the elements, A1,A2...AN. And array B contains the elements, B1,B2...BN. There is a relationship between Ai and Bi, for 1 = i = N, i.e.,
any element Ai lies between 1 and Bi.
Let the cost S of an array A be defined as:
You have to print the largest possible value of S.
The Link to the problem is Problem
Example:
size of array:5
array: 10 1 10 1 10
output : 36 (since the max value can be derived as |10 - 1| + |1 - 10| + |10 - 1| + |1 - 10|)
Approach :
The only approach i could think of was brute force. I thought i would make a overlapping recursive equation so that i could memoize it, but was not able to.
CODE :
public static void func(int pos,int[] arr,int[] aux,int n)
{
/*
* pos is current index in the arr
* arr is array
* aux is temp array which will store one possible combination.
* n is size of the array.
* */
//if reached at the end, check the summation of differences
if(pos == n)
{
long sum = 0;
for(int i = 1 ; i < n ; i++)
{
//System.out.print("i = " + i + ", arr[i] = " + aux[i] + " ");
sum += Math.abs(aux[i] - aux[i - 1]);
}
//System.out.println();
//System.out.println("sum = " + sum);
if(sum > max)
{
max = sum;
}
return;
}
//else try every combination possible.
for(int i = 1 ; i <= arr[pos] ; i++)
{
aux[pos] = i;
func(pos + 1,arr,aux,n);
}
}
NOTE:
The complexity of this is O(n*2^n)
First, there is no reason that a[i] should be equal to any number besides 1 and b[i]. Realizing that we can write down a simple recurrence:
fmax(1) = fone(1) = 0
fmax(i) = max(fone(i-1) + b[i] - 1, fmax(i-1) + abs(b[i]-b[i-1]))
fone(i) = max(fone(i-1), fmax(i-1) + b[i-1] - 1)
answer = max(fmax(N), fone(N))
Where fmax(i) is a maximal sum for a[1..i] elements that end with b[i], fone(i) is a maximal sum for a[1..i] elements that end with 1.
With dynamic programming approach, the complexity is O(N).
I am a newbie trying to understand the working of double pointers and to print double pointers. I increment m by one but it's always pointing to the last value pointed by p. Can someone please help me?
#include <stdio.h>
int main () {
/* an array with 5 elements */
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
double **m;
int i;
p = balance;
m = &p;
/* output each array element's value */
printf( "Array values using pointer\n");
for ( i = 0; i < 5; i++ ) {
printf("*(p + %d) : %f\n", i, *(p+i) );
}
for ( i = 0; i < 5; i++ ) {
printf("**(m + %d) : %f\n", i, *m);
m++;
}
printf( "Array values using balance as address\n");
for ( i = 0; i < 5; i++ ) {
printf("*(balance + %d) : %f\n", i, *(balance + i) );
}
return 0;
}
Your array balance is like this
+--------+--------+--------+--------+--------+
| 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 |
+--------+--------+--------+--------+--------+
After you initialize p and m it is like this:
+---+
| m |
+---+
|
v
+---+
| p |
+---+
|
V
+--------+--------+--------+--------+--------+
| 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 |
+--------+--------+--------+--------+--------+
That is, m points to the location of p, and p points to the first value of the balance array.
When you dereference m (i.e. when you do *m) you get the value of where m is pointing. This value is another pointer (p) that you need to dereference to get to an element in the array.
Using m the second element in balance (i.e. balance[1]) is (*m)[1].
Now if you increment m (with e.g. m++) it will point to the next element of p:
+---+
| m |
+---+
|
v
+---+
| p |
+---+
|
V
+--------+--------+--------+--------+--------+
| 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 |
+--------+--------+--------+--------+--------+
You can clearly see the problem here: It no longer points to p and you can no longer us it to access the balance array. Dereferencing m after the increment will lead to undefined behavior.
Also, for any pointer or array, the array-indexing expression and the pointer arithmetic expression are equal. So for balance, the expression balance[i] is equal to *(balance + i). There is really no difference between them.
So after you execute
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
double **m;
p = balance;
m = &p;
the following are all true:
m == &p // double **
*m == p == &balance[0] // double *
**m == *p == balance[0] // double
(*m)[i] == p[i] == balance[i] // double
Remember that the expression a[i] is defined as *(a + i); given the address a, offset i elements (not bytes1) from that address and dereference the result.
This means that *p is equivalent to *(p + 0), which is equivalent to p[0]. Thus, you can use p[i] in place of balance[i]. Since *m == p, you can also use (*m)[i] in place of p[i]. The parentheses are necessary - unary * has lower precedence than postfix [], so *m[i] would be parsed as *(m[i]), which is not what you want here.
You can increment p directly to "walk" through the balance array:
p = balance; // p == &balance[0];
for ( i = 0; i < 5; i++ )
printf( "%f\n", *p++ );
Each time through the loop, p is incremented to point to the next element of balance.
You can do something similar with the expression (*m):
p = balance; // p == &balance[0]
m = &p;
for ( i = 0; i < 5; i++ )
printf( "%f\n", (*m)++ );
Again, the parentheses around *m are necessary; since postfix ++ has higher precedence than unary *, the expression *m++ would be parsed as *(m++), which is not what we want. We don't want to change the value of m, we want to change the value of what m points to, which in this case is p.
Now, suppose we leave p out of the picture completely; can we do something like:
double balance[5] = { ... };
double **m;
*m = balance;
No. In this example, m is an invalid pointer; it hasn't been initialized to point anywhere meaningful, so *m will invoke undefined behavior (which can include, but is not limited to, a segfault). m has to point to an object of type double * before you can dereference it. There has to be a middleman like p in order for that scheme to work.
Pointer arithmetic always takes the size of the pointed-to type into account - if a points to an object of type T, then a + 1 yields the address of the next object of type T, which may be more than 1 byte away from the current address.
Here is the code I am using. When I run it, it doesn't seem to change anything in the image except the last 1/4 of it. That part turns to a solid color.
void maxFilter(pixel * data, int w, int h)
{
GLubyte tempRed;
GLubyte tempGreen;
GLubyte tempBlue;
int i;
int j;
int k;
int pnum = 0;
int pnumWrite = 0;
for(i = 0 ; i < (h - 2); i+=3) {
for(j = 0 ; j < (w - 2); j+=3) {
tempRed = 0;
tempGreen = 0;
tempBlue = 0;
for (k = 0 ; k < 3 ; k++){
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
if ((data[pnum].g) > tempGreen){tempGreen = (data[pnum + k].g);}
if ((data[pnum].b) > tempBlue){tempBlue = (data[pnum + k].b);}
if ((data[(pnum + w)].r) > tempRed){tempRed = (data[(pnum + w)].r);}
if ((data[(pnum + w)].g) > tempGreen){tempGreen = (data[(pnum + w)].g);}
if ((data[(pnum + w)].b) > tempBlue){tempBlue = (data[(pnum + w)].b);}
if ((data[(pnum + 2 * w)].r) > tempRed){tempRed = (data[(pnum + 2 * w)].r);}
if ((data[(pnum + 2 * w)].g) > tempGreen){tempGreen = (data[(pnum + 2 * w)].g);}
if ((data[(pnum + 2 * w)].b) > tempBlue){tempBlue = (data[(pnum + 2 * w)].b);}
pnum++;
}
pnumWrite = pnum - 3;
for (k = 0 ; k < 3 ; k++){
((data[pnumWrite].r) = tempRed);
((data[pnumWrite].g) = tempGreen);
((data[pnumWrite].b) = tempBlue);
((data[(pnumWrite + w)].r) = tempRed);
((data[(pnumWrite + w)].g) = tempGreen);
((data[(pnumWrite + w)].b) = tempBlue);
((data[(pnumWrite + 2 * w)].r) = tempRed);
((data[(pnumWrite + 2 * w)].g) = tempGreen);
((data[(pnumWrite + 2 * w)].b) = tempBlue);
pnumWrite++;
}
}
}
}
I can see several problems with that code - being difficult to follow not being the least!
I think your main problem is that the loop is (as you probably intended) run through h/3 * w/3 times, once for each 3x3 block in the image. But the pnum index runs only increases by 3 for each block, and reaches a maximum of about h*w/3, rather than the intended h*w. That means that only the first third of your image will be affected by your filter. (And I suspect your painting is done 'bottom-up', so that's why you see the lowest part change. I remember .bmp files being structured that way, but perhaps there are others as well.)
The 'cheap' fix would be to add 2*w at the right point, but nobody will ever understand that code again. I suggest you rewrite your indexing instead, and explicitly compute pnum from i and j in each turn through the loop. That can be improved on for readability, but is reasonably clear.
There's another minor thing: you have code like
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
where the indexing on the right and on the left differ: this is probably also giving you results different from what you intended.
As Jongware points out, writing to the input array is always dangerous - your code is intended, I believe, to avoid that problem by only looking once into each 3x3 block, but his suggestion of a separate output array is very sensible - you probably don't want the blockiness your code gives anyway (you make each 3x3 block all one colour, don't you?), and his suggestion would let you avoid that.
Given an array of 81 elements (meant to represent a 9x9 grid) how can I go over each element, grabbing the three around it and then performing an operation on those, then continuing to the next three of each row, column, or submatrix. Look below or at a sudoku grid to see the layout.
define COL(n) ((n) % 9)
define ROW(n) ((n) / 9)
define SUB(n) ((n / 3) % 9)
For example, I have
int grid[81];
and
int array_x[9], array_y[9], array_s[9];
Since the total 9x9 grid can be split into 9 of the following categories, there are nine elements in each array, and I hope to take the elements of each column (the x axis) in groups of threes, perform
r = ((a = ~a) & (b = ~b)) | ((b | a) & ~c);
// or
r = ((~a & ~b)) | ((~b | ~a) & ~c);
on them, take the three resultant numbers, and perform it on them, and then store it into the array.
If this sounds impossible, sorry, I'd like a different way to do this. Definitely open to suggestions...
Another try:
void applyThingy(int *grid, int xPitch, int yPitch)
{
int row, column;
int *rowPointer = grid;
for(row = 0; row < 3; ++row)
{
int *columnPointer = rowPointer;
for(column = 0; column < 3; ++column)
{
doOperation(columnPointer);
columnPointer += xPitch;
}
rowPointer += yPitch * 9;
}
}
applyThingy(&grid[SUB(n)], 1, 1); // Perform on 3x3 subgrid
applyThingy(&grid[ROW(n)], 1, 0); // Perform on row
applyThingy(&grid[COL(n)], 0, 1); // Perform on column
I'm not sure what you want to do, but is it something like this?:
#define IDX(row, col) ((row)*9+(col))
int m = some_column;
for (int n = 0; n < 9; n += 3) {
a = grid[IDX(n, m)];
b = grid[IDX(n+1, m)];
c = grid[IDX(n+2, m)];
r = ...;
...
}
Also, I'm not sure what you want to do with your operation
r = ((a = ~a) & (b = ~b)) | ((b | a) & ~c);
You're assigning ~a to a, is that what you want? How is a defined, and what are you trying to set it to? What are you trying to achieve?