Swapping Columns/Rows of 1-Dimensional Arrays in C - c

Trying to create two functions (one to swap columns and one to swap rows) of matrices in one-dimensional arrays. Obviously, they'd be structurally similar.
void col_swap(int a[], int col1, int col2, int colSize, int rowSize) {
int d[size];
int space = col2 - col1;
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
if (i == (col1 - 1) || i == (j * (col1-1))) {
d[i+space] = a[i];
} else if (i == (col2 - 1) || i == (j * (col2-1))) {
d[i-space] = a[i];
} else {
d[i] = a[i];
}
}
printf("%d ", d[i]);
if ((i+1) % colSize == 0) {
printf("\n");
}
}
}
Yes, the matrix must be in a one-dimensional array. This doesn't work fully either.
EDIT: COL1 and COL2 are not "the first column of matrix" and "the second column of matrix", respectively. They are any two columns of a matrix that we want to switch.
void row_swap(int a[], int row1, int row2, int rowSize, int colSize) {
for (int i = 0; i < colSize; i++) {
int temp = a[i*rowSize+row1];
a[i*rowSize+row1] = a[i*rowSize+row2];
a[i*rowSize+row2] = temp;
}
for (int i = 0; i < size; i++) {
if (i % colSize == 0) {
printf("\n");
}
printf("%d ", a[i]);
}
}
I have the row_swap function as above but when I give it a matrix
1, 4,
2, 3,
3, 2,
4, 1
It returns
1, 3
2, 4
3, 1
4, 2

This is much easier than you think it would be.
So you want to swap col1 and col2 and here the matrix has rowsize number of rows and colsize number of columns.
void col_swap(int a[], int col1, int col2, int colSize, int rowSize) {
for(int i=0;i<rowSize;i++){
int t=a[i*colSize+col1];
a[i*colSize+col1]=a[i*colSize+col2];
a[i*colSize+col2]=t;
}
}
Just think what is different here. We have just calculate the logic clearly for the position. Then everything is same as standard swapping.
More struturally you can do this:-
void swap(int *a,int*b)
{
int t=*a;
*a=*b;
*b=t;
}
void col_swap(int a[], int col1, int col2, int colSize, int rowSize) {
for(int i=0;i<rowSize;i++){
swap(&a[i*colSize+col1],&a[i*colSize+col2]);
}
}
The rowswapping would be same. It is similar to column swapping if you consider row as columns and vice versa.
Secondly, why do you want to complicate things by making using a 2d array out of a 1d array?
This is hard to use in production level code or more specifically softwares. Why not use the 2d array itself? You should use that instead of doing this.
What was the approach?
After reading the question, I just used paper to get an idea of what is that I want to do and how it maps from 2d array to 1d array. That helps alot of time. And then first coded the first solution. I could see that I can reuse the swapping part in case of Row swapping too. So I take it out and put it in a different function swap.
Sample input output example:
int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
col_swap(a,1,2,3,4);
// 1 2 3
// 4 5 6
// 7 8 9
// 10 11 12
// 1 3 2
// 4 6 5
// 7 9 8
// 10 12 11
Again if you consider:
col_swap(a,0,2,3,4); on the same array results in
// 3 2 1
// 6 5 4
// 9 8 7
// 12 11 10
I have used 0-indexing in the code. So be careful when you give input columns.
Also the other function would be:-
void row_swap(int a[], int row1, int row2, int colSize, int rowSize) {
for(int i=0;i<colSize;i++){
swap(&a[colSize*row1+i],&a[row2*colSize+i]);
}
}

If you are using C99, then pointers to Variable Length Arrays can make the indexing much easier:
void col_swap(int a[], int col1, int col2, int colSize, int rowSize)
{
// Cast 'a' to a pointer to a variable length array of size 'colSize'
int (*a2d_matrix)[colSize] = (int (*)[colSize])a;
// Now we can index into a (through a2d_matrix) as if it really is
// a 2 dimensional matrix
for(int r = 0; r < rowSize; r++)
{
int temp = a2d_matrix[r][col1];
a2d_matrix[r][col1] = a2d_matrix[r][col2];
a2d_matrix[r][col2] = temp;
}
}
I use this method often. Note that this probably works in C11 and greater, however Variable Length Arrays were made optional in the C11 standard. So check your compiler support of optional C11 features. All major vendors support VLAs in C11 as far as I know.

Related

How to fill an empty sudoku board in C

I got an assignment to write a program that fills an empty sudoku board and prints it out.
The tools that we have are only functions, arrays and pointers. No recursion, no search and sort algorithms to improve the time complexity.
So far I thought to use two dimension array for the board and go over every row in a nested "for" loop.
Every time I fetch a number with a random function and check a row, a column and a square (3X3), and if all of them pass then I fill the number.
My problem is that, that way it takes the code a very long time to solve, and I don't know if I'm doing it right. I didn't see a solution of my code yet, even after leaving it to run more than 5 minutes. I thought maybe somehow to use a histogram of numbers from 1-9 that maps which numbers already used to somehow change the use of fetching random numbers, but I'm not really sure how to use it and if it's even right to do so. Basically I'm stuck.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define MATRIX_SIZE 9
#define MAX_NUM 9
void solve_sudoku(int board[MATRIX_SIZE][MATRIX_SIZE]);
void print_sudoku(int board[MATRIX_SIZE][MATRIX_SIZE]);
int rowCheck(int num, int board[][MATRIX_SIZE], int row);
int columnCheck(int num, int board[][MATRIX_SIZE], int row);
int squareCheck(int num, int board[][MATRIX_SIZE], int row, int col);
int giveNum(void);
void main()
{
srand(time(NULL));
int board[MATRIX_SIZE][MATRIX_SIZE];
/*{
0,0,0,0,0,4,0,0,0,
0,6,8,0,0,0,5,0,0,
0,2,0,0,0,0,0,7,6,
6,0,0,0,0,0,8,9,0,
0,0,5,2,6,0,0,0,0,
0,0,0,9,0,0,1,0,0,
0,0,0,0,0,7,0,5,0,
0,4,0,0,0,0,0,0,1,
0,0,0,0,5,1,4,0,0
};*/
for (int row = 0; row < MATRIX_SIZE; row++)
for (int col = 0; col < MATRIX_SIZE; col++)
board[row][col] = -1;
solve_sudoku(board);
print_sudoku(board);
}
void solve_sudoku(int board[MATRIX_SIZE][MATRIX_SIZE])
{
int rowCh, colCh, sqrCh, num, square = 0;
for (int row = 0; row < MATRIX_SIZE; row++)
{
for (int col = 0; col < MATRIX_SIZE; col++)
{
if (square > 2)
square = 0;
while(1)
{
num = giveNum();
rowCh = rowCheck(num, board, row, col);
if (!rowCh)
continue;
colCh = columnCheck(num, board, row, col);
if (!colCh)
continue;
sqrCh = squareCheck(num, board, row, col-square);
if (!sqrCh)
continue;
break;
} //while (!rowCh || !colCh || !sqrCh);
square++;
board[row][col] = num;
}
}
}
void print_sudoku(int board[MATRIX_SIZE][MATRIX_SIZE])
{
printf("Sudoku solution:\n");
for (int i = 0; i < MATRIX_SIZE; i++)
{
for (int j = 0; j < MATRIX_SIZE; j++)
printf("%d ", board[i][j]);
printf("\n");
}
}
int giveNum(void)
{
int num = rand() % MATRIX_SIZE + 1;
return num;
}
int rowCheck(int num, int board[][MATRIX_SIZE], int row)
{
for (int col = 0; col < MATRIX_SIZE; col++)
{
if (num == board[row][col])
return 0;
}
return 1;
}
int columnCheck(int num, int board[][MATRIX_SIZE], int col)
{
for (int row = 0; row < MATRIX_SIZE; row++)
{
if (num == board[row][col])
return 0;
}
return 1;
}
int squareCheck(int num, int board[][MATRIX_SIZE], int row, int col)
{
for (int i = row; i < row + sqrt(MATRIX_SIZE); i++)
for (int j = col; j < col + sqrt(MATRIX_SIZE); j++)
if (board[i][j] == num)
return 0;
return 1;
}
I strongly doubt that you will have much luck with a pure random approach. There are so many combinations so that chance of hitting a valid solution is very little. Instead you'll most likely end in a dead-lock where there is no valid number to put in current position... then you just have an endless loop.
Anyway... here is a bug:
For the squareCheck function to work, it's required that col and row identifies the upper-left corner. For col you ensure that using square but for row you don't.
In other words, your check isn't correct.
Instead of using "the square method" consider to put these lines in the start of the function:
row = row - (row % 3);
col = col - (col % 3);
There's a loop while(1) where you pick a random number and determine if it is valid in the current position.
It's quite possible to get to a dead end here.
You can have easily filled in numbers that while valid individually leave the puzzle insoluble.
You need some method of backtracking if you get 'stuck' or detecting that it will get stuck.
The 'common' approach is to hold a 9x9 matrix of sets holding a subset of 1-9 which are the untried values. When a value is set (at start) or tried (during solve) you check the constraints and remove the value being tried from its column, row and square.
Start with a 9x9 grid all cells initialised to the full range [1-9].
If you set a cell to (say) 5 remove 5 from all cells in that column, row and sub-square.
If that leaves any cell with the empty set, the puzzle is insoluble.
When solving only pick from the set of 'remaining possible values' rather than rand [1-9].
However it still may be that a trial makes the puzzle insoluble and needs to go back a cell (or more) to come forward again.
The easy way to do that would be recursion. But that's ruled out by the Exercise.
So it looks like some kind of Undo stack is required.
Here is a way to generate a random suduko.
// Check that no number 1..9 is present twice in a column
int colok(int s[][9])
{
for (int col=0; col<9; ++col)
{
for (int n=1; n<=9; ++n)
{
int cnt = 0;
for (int i=0; i<9; ++i)
{
if (s[i][col] == n)
{
if (cnt > 0) return 0;
cnt = 1;
}
}
}
}
return 1;
}
// Check that no number 1..9 is present twice in a 3x3 block
int blockok(int s[][9])
{
for (int row=0; row<9; row += 3)
{
for (int col=0; col<9; col +=3)
{
for (int n=1; n<=9; ++n)
{
int cnt = 0;
for (int i=0; i<3; ++i)
{
for (int j=0; j<3; ++j)
{
if (s[i + row][j + col] == n)
{
if (cnt > 0) return 0;
cnt = 1;
}
}
}
}
}
}
return 1;
}
void p(int s[][9])
{
for (int i=0; i<9; ++i)
{
for (int j=0; j<9; ++j)
{
printf("%d ", s[i][j]);
}
puts("");
}
}
#define MAX_LOOP 10000000
void makerow(int s[][9], int r)
{
int loops = 0;
while(1)
{
++loops;
// FY Shuffle row (this ensures that rows are always valid)
int a[] = {1,2,3,4,5,6,7,8,9};
int max = 8;
while(max)
{
int t = rand() % (max + 1);
int tmp = a[t];
a[t] = a[max];
a[max] = tmp;
--max;
}
// Save row
for (int i=0; i<9; ++i)
{
s[r][i] = a[i];
}
// Check whether it's valid
if (colok(s) && blockok(s))
{
// It's valid so stop here
break;
}
// Stop if too many loops
if (loops > MAX_LOOP)
{
puts("I'm so tired...");
exit(1);
}
}
printf("loops %d\n", loops);
}
int main(void)
{
srand((int)time(0));
int s[9][9] = { 0 };
for (int i=0; i<9; ++i)
{
printf("Make row %d\n", i);
makerow(s, i);
}
p(s);
return 0;
}
Possible output:
Make row 0
loops 1
Make row 1
loops 27
Make row 2
loops 1090
Make row 3
loops 3
Make row 4
loops 1019
Make row 5
loops 5521
Make row 6
loops 96
Make row 7
loops 66727
Make row 8
loops 498687
7 5 2 4 6 8 3 1 9
3 4 6 9 1 7 8 2 5
8 1 9 3 2 5 7 6 4
9 6 3 8 7 4 2 5 1
1 8 5 2 9 3 6 4 7
2 7 4 1 5 6 9 8 3
6 9 7 5 4 2 1 3 8
5 2 8 7 3 1 4 9 6
4 3 1 6 8 9 5 7 2
But notice... it happens that no solution can be generated.. then the output is:
Make row 0
loops 1
Make row 1
loops 37
Make row 2
loops 2957
Make row 3
loops 16
Make row 4
loops 2253
Make row 5
I'm so tired...
In order to avoid recursion you can try to navigate the solution space by levels. That requires a Queue, in which you add the next possible states from a given one (just extracted from the queue) and you mark the already visited ones (e.g. with the selected numbers) In this way you only build a single loop (no nested loops required) and you can generate all the possible solutions (but you can stop at the first that just generates a valid position)
Thanks for all of your responses. There is an update: I found a bug that made me a lot of problems, The bug was that I defined : columnCheck function that receives variable row and I called the function this way: " columnCheck(num, board, row, col); ", so the bug is that in the definition I need to give only 3 arguments, when I called the function accidently with 4 and also gave the columCheck the row instead the column. Also rowCheck was called with 4 arguments instead of 3 as defined. Can someone explain why the debugger didn't warn me about that ?
Also I changed the giveNum() function to this one:
int giveNum(void)
{
int static num = 1;
if (num > 9)
num = 1;
return num++;
}
Now it's not random but it fills the sudoku.
Since a lot of people asked the instructor how to do it, he replied that this kind of solution will be fine for now, However I will take the challenge to solve it with your suggestions.

Having trouble dividing a row in a 2D array in C

So I'm currently working on a program that implements Gauss-Jordan elimination on a 2D array (matrix) and I am currently having a bit of a stump just trying to get the first row to divide itself by the first pivot:
void Gauss(int i, int j, int size, int mat [size][size])
{
int x = 0;
for(int i = 0; i < size;i++) {
for(int j = 0; j < size; j++) {
if(mat[i][j]== mat[i][i]) {
mat[0][i] = mat[0][i]/mat[i][i];
mat[i][i] = mat[i][i]/mat[i][i];
mat[i][j] = mat[i][i];
}
}
}
}
Here are is my original mat:
2 2 4
2 1 7
1 3 5
and here is my mat afterwards:
1 2 0
2 1 7
1 3 1
The program keeps dividing the first row by each of the diagonals. Can someone explain why this is occurring and a HINT as to how to fix it? Also, I don't have to worry about any of the pivots already being 0 because this is part of a much larger project that states it won't contain that.
Change this:
void Gauss(int i, int j, int size, int mat [i][j])
to this:
void Gauss(int i, int j, int size, int mat [size][size])
This mat[i][j] = mat[i][i]; has no usefulness, since it only gets executed when mat[i][j]== mat[i][i].
In this kind of applications, people usually use float and not int, but this is of course is not your direct error.

Reordering the rows in a matrix in a specific order

I am successfully storing the calculated subsets in a 2-D array matrix in C language.Now I want to print the subsets in an order desired.
For eg.
2-D array matrix is
10 7 3 2 1
10 7 5 1
7 6 5 3 2
10 6 5 2
10 7 6
Desired Output
10 7 6
10 7 5 1
10 7 3 2 1
10 6 5 2
7 6 5 3 2
How quick sort can be applied to sort/order these rows?
As #chqrlie noted, this can be easily solved with qsort.
Depending on the way the matrix is declared (is it an array of pointers to arrays of ints? do all arrays have the same length? is it a global array of fixed size?) the code will have to do slightly different things.
So, assuming the array is a global variable and all rows have same length (padded with 0s):
MWE:
#include <stdio.h>
#include <stdlib.h>
/*
Compare 2 integers
returns:
-1 if *i1 < *i2
+1 if *i1 > *i2
0 if *i1 == *i2
*/
int intcmp(const int *i1, const int *i2)
{
return (*i2 < *i1) - (*i1 < *i2);
}
#define ROWS 5
#define COLS 5
/*
Assumes rows already sorted in descending order
NOTE: qsort calls the comparison function with pointers to elements
so this function has to be tweaked in case the matrix is an array of
pointers. In that case the function's declaration would be:
int rowcmp(int **pr1, int **pr2)
{
const int *r1 = *pr1;
const int *r2 = *pr2;
// the rest is the same
}
*/
int rowcmp(const int *r1, const int *r2)
{
int i = 0, cmp;
do {
cmp = intcmp(&r1[i], &r2[i]);
i++;
} while (i < COLS && cmp == 0);
return -cmp; /* return -cmp to sort in descending order */
}
int data[5][5] = {
{10,7,3,2,1},
{10,7,5,1,0},
{ 7,6,5,3,2},
{10,6,5,2,0},
{10,7,6,0,0}
};
void printmatrix()
{
int i, j;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
printf("%d ", data[i][j]); /* leaves a trailing space in each row */
}
printf("\n");
}
}
int main()
{
printmatrix();
qsort(data, 5, sizeof(data[0]), (int (*)(const void *, const void *))rowcmp);
printf("\n");
printmatrix();
return 0;
}
For the most flexible solution, I would define
struct row {
size_t len;
int *elems;
};
struct matrix {
struct row *rows;
size_t nrows;
};
and change the code accordingly.
NOTE: code not thoroughly tested, use with caution ;)
First of all, are you sure that the 1 on row 3,col 5 should be there and not on the last line?
Anyway, an efficient way to achieve what you want is:
compute the frequency array
declare a new matrix
go from the highest element (10 in your case) from frequency array and put in your matrix using your desired format.
It is time-efficient because you don't use any sorting algorithm, thus you don't waste time there.
It is NOT space-efficient because you use 2 matrices and 1 array, instead of only 1 matrix as suggested in other posts, but this should not be a problem, unless you use matrices of millions of rows and columns
C code for frequency array:
int freq[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for(int i=0; i<NO_ROWS; i++) {
for(int j=0; j<NO_COLS; j++) {
if(MATRIX[i][j]!=null && MATRIX[i][j]>0 && MATRIX[i][j]<11) {
freq[MATRIX[i][j]]++;
}
}
}
C code for computing the new matrix dimensions
(assuming you want to keep the number of rows)
OUTPUT_MATRIX[100][100] /*I declared it statically, but I would advise to make it dinamically */
/* first, compute the number columns.
To do so, we need the number of elements
(we get them by simply summing up frequency array's elements) */
int s=0;
for(int i=0; i<11; i++) {
s+=frequency[i];
}
int addOne = 0 /* boolean value to check if we will have to add one extra column for safety */
if(s % NO_ROWS) {
addOne = 1; /* division is not even, so we will have to add extra column */
}
NO_COLS = s/NO_ROWS + addOne;
Now, final part, assigning the values from frequency array to the OUTPUT_MATRIX
int k=0;
int currentNumber = 10; /* assigning starts from 10 */
for(int i=0; i<NO_ROWS; i++) {
for(int j=0; j<NO_COLS; j++) {
if(currentNumber>0) {
if(frequency[currentNumber]==0 || k>=frequency[currentNumber]) {
currentNumber--;
k=0;
}
OUTPUT_MATRIX[i][j] = frequency[currentNumber];
k++;
} else {/*here, you can assign the rest of the value with whatever you want
I will just put 0's */
OUTPUTMATRIX[i][j] = 0;
}
}
}
Hope this helps!
This is what I do in C++ to reorder a matrix:
// b is the matrix and p is an array of integer containing the desired order of rows
for(i=0; i<n; i++){
if( p[i]==i )
continue;
b[i].swap(b[p[i]]);
j = p[i]; // New row i position
// Update row i position to new one
for(int k=i+1; k<n; k++){
if( p[k] == i )
p[k] = j;
}
printRow( b[i] );
}
You need to define an array of pointers of the data type you use and then you can reorder your matrix.
for example your matrix is: arr[5][10], and you want to print line 4 before line 3:
int *[5] arr2;
arr2[0] = &arr[0][0];
arr2[1] = &arr[1][0];
arr2[2] = &arr[2][0];
arr2[3] = &arr[4][0];
arr2[4] = &arr[3][0];
in regard to how will the ordering algorithm work, i would suggest placing a header in the start of each array in the matrix which will tell you how many elements it has(basically the first element of each array can be a counter of the total elements) afterwards you can order the strings by comparing the header, and if it is equal comparing the first element and so on. this can be done in a loop that iterates as many times as there are elements in the array, when the elements are not equal, break out of the loop.
hope this helps.

Rearranging an array with respect to another array

I have 2 arrays, in parallel:
defenders = {1,5,7,9,12,18};
attackers = {3,10,14,15,17,18};
Both are sorted, what I am trying to do is rearrange the defending array's values so that they win more games (defender[i] > attacker[i]) but I am having issues on how to swap the values in the defenders array. So in reality we are only working with the defenders array with respect to the attackers.
I have this but if anything it isn't shifting much and Im pretty sure I'm not doing it right. Its suppose to be a brute force method.
void rearrange(int* attackers, int* defenders, int size){
int i, c, j;
int temp;
for(i = 0; i<size; i++){
c = 0;
j = 0;
if(defenders[c]<attackers[j]){
temp = defenders[c+1];
defenders[c+1] = defenders[c];
defenders[c] = temp;
c++;
j++;
}
else
c++;
j++;
}
}
Edit: I did ask this question before, but I feel as if I worded it terribly, and didn't know how to "bump" the older post.
To be honest, I didn't look at your code, since I have to wake up in less than 2.30 hours to go to work, hope you won't have hard feelings for me.. :)
I implemented the algorithm proposed by Eugene Sh. Some links you may want to read first, before digging into the code:
qsort in C
qsort and structs
shortcircuiting
My approach:
Create merged array by scanning both att and def.
Sort merged array.
Refill def with values that satisfy the ad pattern.
Complete refilling def with the remaining values (that are
defeats)*.
*Steps 3 and 4 require two passes in my approach, maybe it can get better.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char c; // a for att and d for def
int v;
} pair;
void print(pair* array, int N);
void print_int_array(int* array, int N);
// function to be used by qsort()
int compar(const void* a, const void* b) {
pair *pair_a = (pair *)a;
pair *pair_b = (pair *)b;
if(pair_a->v == pair_b->v)
return pair_b->c - pair_a->c; // d has highest priority
return pair_a->v - pair_b->v;
}
int main(void) {
const int N = 6;
int def[] = {1, 5, 7, 9, 12, 18};
int att[] = {3, 10, 14, 15, 17, 18};
int i, j = 0;
// let's construct the merged array
pair merged_ar[2*N];
// scan the def array
for(i = 0; i < N; ++i) {
merged_ar[i].c = 'd';
merged_ar[i].v = def[i];
}
// scan the att array
for(i = N; i < 2 * N; ++i) {
merged_ar[i].c = 'a';
merged_ar[i].v = att[j++]; // watch out for the pointers
// 'merged_ar' is bigger than 'att'
}
// sort the merged array
qsort(merged_ar, 2 * N, sizeof(pair), compar);
print(merged_ar, 2 * N);
// scan the merged array
// to collect the patterns
j = 0;
// first pass to collect the patterns ad
for(i = 0; i < 2 * N; ++i) {
// if pattern found
if(merged_ar[i].c == 'a' && // first letter of pattern
i < 2 * N - 1 && // check that I am not the last element
merged_ar[i + 1].c == 'd') { // second letter of the pattern
def[j++] = merged_ar[i + 1].v; // fill-in `def` array
merged_ar[i + 1].c = 'u'; // mark that value as used
}
}
// second pass to collect the cases were 'def' loses
for(i = 0; i < 2 * N; ++i) {
// 'a' is for the 'att' and 'u' is already in 'def'
if(merged_ar[i].c == 'd') {
def[j++] = merged_ar[i].v;
}
}
print_int_array(def, N);
return 0;
}
void print_int_array(int* array, int N) {
int i;
for(i = 0; i < N; ++i) {
printf("%d ", array[i]);
}
printf("\n");
}
void print(pair* array, int N) {
int i;
for(i = 0; i < N; ++i) {
printf("%c %d\n", array[i].c, array[i].v);
}
}
Output:
gsamaras#gsamaras:~$ gcc -Wall px.c
gsamaras#gsamaras:~$ ./a.out
d 1
a 3
d 5
d 7
d 9
a 10
d 12
a 14
a 15
a 17
d 18
a 18
5 12 18 1 7 9
The problem is that you are resetting c and j to zero on each iteration of the loop. Consequently, you are only ever comparing the first value in each array.
Another problem is that you will read one past the end of the defenders array in the case that the last value of defenders array is less than last value of attackers array.
Another problem or maybe just oddity is that you are incrementing both c and j in both branches of the if-statement. If this is what you actually want, then c and j are useless and you can just use i.
I would offer you some updated code, but there is not a good enough description of what you are trying to achieve; I can only point out the problems that are apparent.

Splitting a 2D array to an array of smaller 2D arrays in C

Given:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
I want to split the 2d array (struct MATRIX) into the an array of struct MATRIX
given a chunksize CS:
assume cs to be 2,
the answer would be
Seg[0]:
1 2
1 2
1 2
Seg[1]:
3 4
3 4
3 4
....
Seg[3]:
7 8
7 8
7 8
Here is my Matrix Struct:
typedef struct MATRIX {
int nrow;
int ncol;
int **element;
} MATRIX;
and here is the function the seperates them:
void SegmentMatrix(MATRIX input,MATRIX* segs,int Chunksize, int p) {
int i,j,r;
//Allocate segs
for (i = 0; i<p;i++)
{
CreateMatrix(&(segs[i]),input.nrow ,Chunksize,0);
}
//Now Copy the elements from input to the segs
//where seg0 takes from 0 to cs cols of a, and all their rows, and seg1 takes from cs to 2cs ...
printf("Stats:\n\t P: %d\t CS: %d\n",p,Chunksize);
for (r = 0; r<p; r++) {
for (i = 0; i<input.nrow;i++) {
for (j = r*Chunksize; j<r*Chunksize+Chunksize-1; j++) {
//I tried (&(segs[r]))->element... Doesn't work, produces wrong data
segs[r].element[i][j] = input.element[i][j];
}
}
PRINTM(segs[r]);
}
}
Note that PRINTM basically prints the matrix, it knows the limits by checking segs[r].nrow and ncol
and CreateMatrix takes the following inputs (&matrix, number of rows, number of colums, filltype) and mallocs from within.
filltype:
0- generates zeroth matrix
1- generates identity
else A[i][j] = j; for simplicity
The problem is that the if i print the matrices Segs[i], they all come down with their default value given by CreateMatrix, and not the newly added values.
CLARIFICATION:
Okay, so if you guys check that last PRINTM in SegmentMatrix function, it outputs the matrices as if the for loops didn't happen, aka, i can delete the for loops and would get the same output..
did i do something wrong in this line (taken from the SegmentMatrix)
Segs[r].element[i][j] = input.element[i][j];
I don't see why and what you are manipulating with multiplication by ChunkSize and r (which is uninitialized anyway), I'd suggest simplifying the code (rule of thumb: if it seems messy, it's too complex). All you need is a 3-dimensional array to store the array of chunks, and modulo arithmetic plus integer division to insert into the appropriate column of the appropriate chunk:
/* the variable-sized dimension of the `chunks' argument is w / chsz elements big
* (it's the number of chunks)
*/
void split(int h, int w, int mat[h][w], int chsz, int chunks[][h][chsz])
{
/* go through each row */
for (int i = 0; i < h; i++) {
/* and in each row, go through each column */
for (int j = 0; j < w; j++) {
/* and for each column, find which chunk it goes in
* (that's j / chsz), and put it into the proper row
* (which is j % chsz)
*/
chunks[j / chsz][i][j % chsz] = mat[i][j];
}
}
}
Demonstration, a. k. a. how to call it:
int main(int agrc, char *argv[])
{
const size_t w = 8;
const size_t h = 3;
const size_t c = 2;
int mat[h][w] = {
{ 1, 2, 3, 4, 5, 6, 7, 8 },
{ 1, 2, 3, 4, 5, 6, 7, 8 },
{ 1, 2, 3, 4, 5, 6, 7, 8 }
};
int chunks[w / c][h][c];
split(h, w, mat, c, chunks);
for (int i = 0; i < w / c; i++) {
for (int j = 0; j < h; j++) {
for (int k = 0; k < c; k++) {
printf("%3d ", chunks[i][j][k]);
}
printf("\n");
}
printf("\n\n");
}
return 0;
}
Question was unclear . so i thought he wanted just to know how to achieve this.
So i wrote this simple Pseudo code . Otherwise accept my apologize :
matrix[i] matrix
//matrixes total column size should be bigger big 2d array column size
first condition check: sum(matrix[i].colsize)>=big2d.colsize
//in this simple code raw sizes must be equal
second condition: for all i matrix[i].rawsize=big2d.rawsize
//if columns sizes will be equal the algorithm could be simplified , does not mean optimized
//splitting big2d into matrixes
for (int br=0;br<big2d.rawsize;br++){
i=0;//store matrix index
int previndex=0;//store offset for next matrix
for(int bc=0;bc<big2d.colsize;bc++){
matrix[i].val[bc-previndex][br]=big2d.val[bc][br]; //assign (bc,br)
if(bc-previndex==matrix[i].colsize-1){
i++; //move to next matrix;//if we not have next matrix then break;
previndex=bc+1;
}
/*if it be for equal chunks matrixes offset can be calculated this way too
matrix[bc/chunk].val[bc%chunk][br]=big2d.val[bc][br];
*/
}//loop columns
}//loop raws

Resources