Reputation: 117
I am really stucked on this problem, my C code has worked very well using multidimensional arrays but i need to do the same using pointers but i'll describe the problem first.
Having the following matrix, i will get a number which will be the number of permutations (the number of swapping of columns that will move to the right and the last column will move to the first column).
For example
The number of column's permutations: 5
| 1 2 3 | -----> | 2 3 1 |
| 3 1 2 | -----> | 1 2 3 |
| 2 3 1 | -----> | 3 1 2 |
I wrote the following code using pointers, as you can see i build the matrix with multidimensional array and assign all of it into a pointer:
short elementMatrix[3][3] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short *element_matrix;
element_matrix = *elementMatrix;
int counter = 1;
while (counter <= 5)
{
for (int i = 0; i < 3; i++)
{
int temp = elementMatrix[i][PR.elem_mat_size - 1];
*outElementMatrix = *outElementMatrix + i * PR.elem_mat_size + PR.elem_mat_size - 1;
for (int j = 3 - 1; j >= 0; j--)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *(outElementMatrix + i * PR.elem_mat_size + j - 1);
if (j == 0)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *outElementMatrix;
}
}
}
counter++;
}
Upvotes: 2
Views: 1150
Reputation: 12749
You can consider the permutations as a rotation of each row in the matrix and, unless you have to somehow use the matrix after each step, calculate only the final result.
I'll use an extra buffer to help with the swaps.
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
// rotate the values of an array using a buffer to ease the swappings
void rotate_(size_t n, void *arr, void *tmp, size_t offset)
{
assert(n && arr && tmp && offset <= n);
// casting to perform pointer arithmetic
memcpy(tmp, (char *)arr + (n - offset), offset);
memmove((char *)arr + offset, arr, n - offset);
memcpy(arr, tmp, offset);
}
void rotate_columns_short(size_t r, size_t c, short mat[r][c], short *buf, int n)
{
// clamp the value of the offset to the number of columns
size_t offset = (n >= 0
? n % c
: c - -n % c) * sizeof(short);
// transform each row
for (short *row = &mat[0][0], *row_end = row + r * c;
row != row_end;
row += c)
{
rotate_(c * sizeof(short), row, buf, offset);
}
}
void print_matrix_short(size_t r, size_t c, short mat[r][c])
{
for (size_t i = 0; i < r; ++i)
{
for (size_t j = 0; j < c; ++j)
{
printf(" %hd", mat[i][j]);
}
puts("");
}
}
#define ROWS 3
#define COLS 3
int main(void)
{
short matrix[ROWS][COLS] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short buf[COLS];
print_matrix_short(ROWS, COLS, matrix);
puts("");
rotate_columns_short(ROWS, COLS, matrix, buf, 5);
print_matrix_short(ROWS, COLS, matrix);
}
The output beeing:
1 2 3 3 1 2 2 3 1 2 3 1 1 2 3 3 1 2
Upvotes: 0
Reputation: 16876
Since you want to swap out columns, it makes sense to have the pointers represent the columns. That way, you can swap a pointer to swap a column. So let's have an array of 3 pointers to a column.
short* col[3];
Each column consists of 3 short
s, so allocate that much memory.
for (int i = 0; i < 3; i++) {
col[i] = (short*)malloc(3 * sizeof(short));
}
Now to initialize the Matrix. This is a bit verbose, so if anyone knows a better way, edit away. :)
col[0][0] = 1; col[1][0] = 2; col[2][0] = 3;
col[0][1] = 3; col[1][1] = 1; col[2][1] = 2;
col[0][2] = 2; col[1][2] = 3; col[2][2] = 1;
Now we do the swap. Note how you need a temp variable, like Rishikesh Raje suggested. Also note that three swaps bring it back to the original, so instead of swapping n
times, you only have to swap n % 3
times. Of course it's going to be pretty much instant with 5 or 2 swaps, but if you have to do like a billion, the difference should be noticeable.
for (int i = 0; i < 5; i++) {
short* temp = col[2];
col[2] = col[1];
col[1] = col[0];
col[0] = temp;
}
We assure that the result is correct by printing it:
for (int i = 0; i < 3; i++) {
printf("%d %d %d\n", col[0][i], col[1][i], col[2][i]);
}
Upvotes: 1