How to rearrange a two dimensional array - c

I want to assign the values in one array to another, but in a different
order. For example the original array would be:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
And the desired array is:
8 11 14 3 6 16 19
9 12 1 4 7 17 20
10 13 2 5 15 18 21
How would I do this? In the code below I moved a selected row to the center, then assigned each array individually. I can't figure out a better way.
int main()
{
int decide, i, j, k;
int save[3][7];
int shuffle[3][7];
int arr[3][7] = {
{1, 2, 3, 4, 5, 6, 7},
{8, 9, 10, 11, 12, 13, 14},
{15, 16, 17, 18, 19, 20, 21}
};
printf("Select a number between 1 and 21\n\n0-GroupA (1 - 7))\n1-GroupB ( 8 - 14)\n2-GroupC (15 - 21)\n\n");
for(k = 0 ; k < 1 ; ++k)
{
printf("Select which group the number falls into:");
scanf("%d", &decide);
for(j = 0 ; j < 7 ; ++j)
{/*moves selected row to middle row of array*/
save[0][j] = arr[1][j];
arr[1][j] = arr[decide][j];
arr[decide][j] = save[0][j];
}
/*this is a horrible method*/
shuffle[0][0] = arr[0][0];
shuffle[1][0] = arr[0][1];
shuffle[2][0] = arr[0][2];
shuffle[0][1] = arr[0][3];
shuffle[1][1] = arr[0][4];
shuffle[2][1] = arr[0][5];
shuffle[0][2] = arr[0][6];
shuffle[1][2] = arr[1][0];
shuffle[2][2] = arr[1][1];
shuffle[0][3] = arr[1][2];
shuffle[1][3] = arr[1][3];
shuffle[2][3] = arr[1][4];
shuffle[0][4] = arr[1][5];
shuffle[1][4] = arr[1][6];
shuffle[2][4] = arr[2][0];
shuffle[0][5] = arr[2][1];
shuffle[1][5] = arr[2][2];
shuffle[2][5] = arr[2][3];
shuffle[0][6] = arr[2][4];
shuffle[1][6] = arr[2][5];
shuffle[2][6] = arr[2][6];
}

like this ?
#include <stdio.h>
#define ROWS 3
#define COLS 7
int main(void){
int arr[ROWS][COLS] = {
{1, 2, 3, 4, 5, 6, 7},
{8, 9, 10, 11, 12, 13, 14},
{15, 16, 17, 18, 19, 20, 21}
};
int result[ROWS][COLS];
int order[ROWS] = {1, 0, 2};
int n = sizeof(arr)/sizeof(**arr);//number of elements
int r = 0, c = 0, i = 0, j = 0;
while(n--){
result[r++][c] = arr[order[i]][j++];
if(r == ROWS){
r = 0;
c += 1;
}
if(j == COLS){
j = 0;
i += 1;
}
}
//check print
for(r = 0; r < ROWS; ++r){
for(c = 0; c < COLS; ++c)
printf("%-2d ", result[r][c]);
puts("");
}
}

The transposition part can be done like this:
#include <stdio.h>
typedef struct Sequence2D
{
int idx_slow;
int idx_fast;
int max_slow;
int max_fast;
} Sequence2D;
static inline void next2D(Sequence2D *seq)
{
if (++seq->idx_fast == seq->max_fast)
{
seq->idx_fast = 0;
if (++seq->idx_slow == seq->max_slow)
seq->idx_slow = 0;
}
}
static inline void dump2D(const char *tag, int rows, int cols, int data[rows][cols])
{
printf("%s:\n", tag);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
printf("%3d", data[r][c]);
putchar('\n');
}
}
enum { ROWS = 3, COLS = 7 };
int main(void)
{
int src[ROWS][COLS] =
{
{ 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19, 20, 21 },
};
int dst[ROWS][COLS];
Sequence2D dst2D = { 0, 0, COLS, ROWS };
Sequence2D src2D = { 0, 0, ROWS, COLS };
dump2D("Source", ROWS, COLS, src);
for (int i = 0; i < ROWS * COLS; i++)
{
dst[dst2D.idx_fast][dst2D.idx_slow] = src[src2D.idx_slow][src2D.idx_fast];
printf("dst[%d][%d] = src[%d][%d] = %d\n",
dst2D.idx_fast, dst2D.idx_slow,
src2D.idx_slow, src2D.idx_fast,
dst[dst2D.idx_fast][dst2D.idx_slow]);
next2D(&dst2D);
next2D(&src2D);
}
dump2D("Target", ROWS, COLS, dst);
return 0;
}
The Sequence2D structure plus the next2D() function cycle through array indexes, changing the fast index on each call of next2D() and the slow index when necessary. This saves you writing out the sequence of 21 assignments, and immediately scales to other shapes without requiring much extra work on your part. Indeed, it would not take much to handle all the sizes as run-time inputs instead of compile-time constants.
The output of this code is:
Source:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
dst[0][0] = src[0][0] = 1
dst[1][0] = src[0][1] = 2
dst[2][0] = src[0][2] = 3
dst[0][1] = src[0][3] = 4
dst[1][1] = src[0][4] = 5
dst[2][1] = src[0][5] = 6
dst[0][2] = src[0][6] = 7
dst[1][2] = src[1][0] = 8
dst[2][2] = src[1][1] = 9
dst[0][3] = src[1][2] = 10
dst[1][3] = src[1][3] = 11
dst[2][3] = src[1][4] = 12
dst[0][4] = src[1][5] = 13
dst[1][4] = src[1][6] = 14
dst[2][4] = src[2][0] = 15
dst[0][5] = src[2][1] = 16
dst[1][5] = src[2][2] = 17
dst[2][5] = src[2][3] = 18
dst[0][6] = src[2][4] = 19
dst[1][6] = src[2][5] = 20
dst[2][6] = src[2][6] = 21
Target:
1 4 7 10 13 16 19
2 5 8 11 14 17 20
3 6 9 12 15 18 21
If you rearrange the initial matrix (src) according to whatever arcane rules you're using before you copy the 'transpose' of src into the result (dst), then you should be able to get the result you desire.
As noted, the code can be generalized rather easily using C99 and variable-length arrays:
#include <assert.h>
#include <stdio.h>
typedef struct Sequence2D
{
int idx_slow;
int idx_fast;
int max_slow;
int max_fast;
} Sequence2D;
static inline void next2D(Sequence2D *seq)
{
if (++seq->idx_fast == seq->max_fast)
{
seq->idx_fast = 0;
if (++seq->idx_slow == seq->max_slow)
seq->idx_slow = 0;
}
}
static inline void dump2D(const char *tag, int rows, int cols, int data[rows][cols])
{
printf("%s:\n", tag);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
printf("%3d", data[r][c]);
putchar('\n');
}
}
static void transpose(int rows, int cols)
{
assert(rows * cols < 1000000);
int src[rows][cols];
int dst[rows][cols];
Sequence2D dst2D = { 0, 0, cols, rows };
Sequence2D src2D = { 0, 0, rows, cols };
int cells = rows * cols;
for (int i = 0; i < cells; i++)
{
src[src2D.idx_slow][src2D.idx_fast] = i;
next2D(&src2D);
}
/* src2D is back to its initial state! */
dump2D("Source", rows, cols, src);
for (int i = 0; i < cells; i++)
{
dst[dst2D.idx_fast][dst2D.idx_slow] = src[src2D.idx_slow][src2D.idx_fast];
printf("dst[%d][%d] = src[%d][%d] = %d\n",
dst2D.idx_fast, dst2D.idx_slow,
src2D.idx_slow, src2D.idx_fast,
dst[dst2D.idx_fast][dst2D.idx_slow]);
next2D(&dst2D);
next2D(&src2D);
}
dump2D("Target", rows, cols, dst);
}
int main(void)
{
transpose(3, 7);
transpose(9, 4);
return 0;
}
The first section of the output is the same as before; the 9x4 part looks like:
Source:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19
20 21 22 23
24 25 26 27
28 29 30 31
32 33 34 35
dst[0][0] = src[0][0] = 0
dst[1][0] = src[0][1] = 1
dst[2][0] = src[0][2] = 2
dst[3][0] = src[0][3] = 3
dst[4][0] = src[1][0] = 4
dst[5][0] = src[1][1] = 5
dst[6][0] = src[1][2] = 6
dst[7][0] = src[1][3] = 7
dst[8][0] = src[2][0] = 8
dst[0][1] = src[2][1] = 9
dst[1][1] = src[2][2] = 10
dst[2][1] = src[2][3] = 11
dst[3][1] = src[3][0] = 12
dst[4][1] = src[3][1] = 13
dst[5][1] = src[3][2] = 14
dst[6][1] = src[3][3] = 15
dst[7][1] = src[4][0] = 16
dst[8][1] = src[4][1] = 17
dst[0][2] = src[4][2] = 18
dst[1][2] = src[4][3] = 19
dst[2][2] = src[5][0] = 20
dst[3][2] = src[5][1] = 21
dst[4][2] = src[5][2] = 22
dst[5][2] = src[5][3] = 23
dst[6][2] = src[6][0] = 24
dst[7][2] = src[6][1] = 25
dst[8][2] = src[6][2] = 26
dst[0][3] = src[6][3] = 27
dst[1][3] = src[7][0] = 28
dst[2][3] = src[7][1] = 29
dst[3][3] = src[7][2] = 30
dst[4][3] = src[7][3] = 31
dst[5][3] = src[8][0] = 32
dst[6][3] = src[8][1] = 33
dst[7][3] = src[8][2] = 34
dst[8][3] = src[8][3] = 35
Target:
0 9 18 27
1 10 19 28
2 11 20 29
3 12 21 30
4 13 22 31
5 14 23 32
6 15 24 33
7 16 25 34
8 17 26 35

You can't transpose a matrix in place. That is to say, it is not possible to write a function which will take a matrix and modify it so that it is its transpose, without creating a temporary matrix of equal size. At least without some very fancy programming.
Now your task isn't exactly the transpose, but it seems to be very similar. So I wouldn't expect there to be a nice, in place solution. You must simply create a temporary, apply the mapping from input to temporary, and write the values back.
What might help is this.
/* swap two rows of a matrix */
void swaprows(int *mtx, int width, int height, int rowa, int rowb)
{
int i;
for(i=0;i<width;i++)
{
int temp = mtx[rowa*width+i];
mtx[rowa*width+i] = mtx[rowb*width+i];
mtx[rowa*width+i] = temp;
}
}
/* transpose a matrix */
int transpose(int *mtx, int width, int height)
{
int *tmtx = malloc(width*height*sizeof(int));
if(!tmtx)
return -1;
for(y=0;y<width;y++)
for(x=0;x<height;x++)
tmtx[y*height+x] = mtx[x*width+y];
mempy(mtx, tmtx, width * height * sizeof(int));
free(tmtx);
}
/* your logic */
int arr[3][7] = {
{1, 2, 3, 4, 5, 6, 7},
{8, 9, 10, 11, 12, 13, 14},
{15, 16, 17, 18, 19, 20, 21}
};
swaprows((int *) arr, 7, 3, 0, 1);
transpose(int *) arr, 7, 3);
This seems to be what you are trying to do.

Related

print evens number and odds number from an array

Declare an array containing these number and print the evens numbers and odd numbers
Now I initialized an array that containing 11 integers.
Here is my code
#include <stdio.h>
int main(void) {
int nums[11] = {11,3,9,7,6,10,13,17,2,8,3}; // create an variables that store integers
int evens[11] = {0}; // initialized an array to store even numbers
int odds[11] = {0}; // initialized an array to store even numbers
int length = sizeof(nums) / sizeof(nums[0]); // get the length of nums
int nums_index = 0;
int evens_index = 0;
int odds_index = 0;
for (nums_index; nums_index < length;nums_index++) {
if (nums[nums_index] % 2 == 0) {
evens[evens_index] = nums[nums_index];
evens_index++;
}
else if(nums[nums_index] % 2 != 0) {
odds[odds_index] = nums[nums_index];
odds_index++;
}
printf("%d\n",evens[evens_index]);
printf("%d\n",odds[odds_index]);
}
return 0;
}
The major question is whether the output has problems when I compile my code.
The output is :0 11 0 3 0 9 0 7 6 0 10 0 0 13 0 17 2 0 8 0 0 3
Why it could happened?
Thank you all.
You need separate indexing for each array, advancing the index for evens and odds only when nums[i] value is one of the two.
Otherwise you would get sort of a copy of nums with zeroes in place of those numbers of the opposite type (odd/even).
For instance:
int j = 0;
int k = 0;
for (int i = 0; i < length; i++) {
if (nums[i] % 2 == 0) {
evens[j] = nums[i];
j++;
}
else if(nums[i] % 2 != 0) {
odds[k] = nums[i];
k++;
}
printf("%d\n",evens[i]);
printf("%d\n",odds[i]);
}
This will compose the arrays like:
11 3 9 7 13 17 3 0 0 0 0 --- for odds
6 10 2 8 0 0 0 0 0 0 0 0 --- for evens
The second problem is that you are printing inside the loop, firstly a value from evens and immediately after a value for odds.
So if you want to display them nice and separate, you can move both printf outside the first loop, then looping again on each result array for displaying it completely, before proceding to the other.
#include <stdio.h>
void PrintNumbers(int*, int);
int main(void) {
int nums[11] = {11,3,9,7,6,10,13,17,2,8,3}; // create an variables that store integers
int evens[11] = {0}; // initialized an array to store even numbers
int odds[11] = {0}; // initialized an array to store even numbers
int length = sizeof(nums) / sizeof(nums[0]); // get the length of nums
int nums_index = 0;
int evens_index = 0;
int odds_index = 0;
for (nums_index; nums_index < length; nums_index++)
{
if (nums[nums_index] % 2 == 0)
{
evens[evens_index] = nums[nums_index];
evens_index++;
}
else if(nums[nums_index] % 2 != 0)
{
odds[odds_index] = nums[nums_index];
odds_index++;
}
}
printf("Original List: ");
PrintNumbers(nums, length);
printf("Even numbers: ");
PrintNumbers(evens, length);
printf("Odd numbers: ");
PrintNumbers(odds, length);
return 0;
}
void PrintNumbers(int* numbers, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d, ", numbers[i]);
}
printf("\n");
}
Output:
Original List: 11, 3, 9, 7, 6, 10, 13, 17, 2, 8, 3,
Even numbers: 6, 10, 2, 8, 0, 0, 0, 0, 0, 0, 0,
Odd numbers: 11, 3, 9, 7, 13, 17, 3, 0, 0, 0, 0,

reading and printing matrix from stdin

Well I posted this before but it's kinda improved now, and I only have one problem (I guess).
The assignment was to write a function which reads an integer matrix given in a ‘.txt file’ using
I/O redirection, then write another function to print it.
I read txt into a 1D array (arr) then create 2D matrix (mat) out of it, before those, I allocated memory dynamically bc our professor asked to do it that way. The problem is that arr seems to be changing when I put it on for loop and try to address it for the matrix. I would appreciate any ideas... Also, it would be helpful if you guys can comment on my way of allocating memory. (Don't forget we have 3 different input.txts some of them has -5.58234 like values or they are not seperated by "," in this example, so I want to make my code usable in any cases)
example txt file:
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int readMatrix(int *arr, int **mat);
void printMatrix(int **mat, int size);
int main(){
// declare 1D array and allocate memory
int *arr;
arr = malloc(sizeof(stdin)*sizeof(int));
// declare 2D Matrix and allocate memory
int **mat;
mat = (int **)malloc(sizeof(stdin)*sizeof(int));
// function implementations
int size;
size = readMatrix(arr, mat);
printMatrix(mat,size);
return 0;
}
int readMatrix(int *arr, int **mat){
// reading
int i=0, size=0; // loop var i and size to count the elements of array
while(scanf("%d,", &arr[i]) != EOF)
{
i++;
size++;
}
printf("arr[63] = %d \n\n",arr[63]); // VALUE IS CORRECT HERE
// finding row and column numbers
int rows = sqrt(size), cols = rows;
// appending 1d array into matrix
int m = 0;
// test printf("rows = %d, cols = %d\n", rows, cols);
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
printf("arr[%d] = %d\n",m, arr[m]); // VALUES OF arr[] BECAME WEIRD AFTER arr[12]
//mat[i][j] = arr[m]; // segmentation fault
//*(*(mat+i)+j) = arr[m]; // segmentation fault
//*(*(mat+i)+j) = &arr[m]; // segmentation fault
*(mat + i*cols + j) = &arr[m]; // I don't know if this is the proper way but it works
m++;
}
}
printf("\narr[63] = %d\n",arr[63]); // HOWWWWW
// return size for further implementations
//
return size;
}
void printMatrix(int **mat, int size){
int rows = sqrt(size), cols = rows;
printf("\nMATRIX A:\n");
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++)
{
printf("%d ", mat[i][j]);
//if(mat[i][j]>=10 && mat[i][j]<100 ){printf("%d ", mat[i][j]);}
//else if(mat[i][j]>=100 ){printf("%d ", mat[i][j]);}
//else{printf("%d ", mat[i][j]);}
}
printf("\n");
}
}
output:
$ ./secondtry < input1.txt
arr[63] = 99
arr[0] = 16
arr[1] = 11
arr[2] = 10
arr[3] = 16
arr[4] = 24
arr[5] = 40
arr[6] = 51
arr[7] = 61
arr[8] = 12
arr[9] = 12
arr[10] = 14
arr[11] = 19
arr[12] = 976
arr[13] = 8
arr[14] = 980
arr[15] = 8
arr[16] = 984
arr[17] = 8
arr[18] = 988
arr[19] = 8
arr[20] = 992
arr[21] = 8
arr[22] = 996
arr[23] = 8
arr[24] = 1000
arr[25] = 8
arr[26] = 1004
arr[27] = 8
arr[28] = 1008
arr[29] = 8
arr[30] = 1012
arr[31] = 8
arr[32] = 1016
arr[33] = 8
arr[34] = 1020
arr[35] = 8
arr[36] = 1024
arr[37] = 8
arr[38] = 1028
arr[39] = 8
arr[40] = 1032
arr[41] = 8
arr[42] = 1036
arr[43] = 8
arr[44] = 1040
arr[45] = 8
arr[46] = 1044
arr[47] = 8
arr[48] = 1048
arr[49] = 8
arr[50] = 1052
arr[51] = 8
arr[52] = 1056
arr[53] = 8
arr[54] = 1060
arr[55] = 8
arr[56] = 1064
arr[57] = 8
arr[58] = 1068
arr[59] = 8
arr[60] = 1072
arr[61] = 8
arr[62] = 1076
arr[63] = 8
arr[63] = 8
MATRIX A:
16 11 10 16 24 40 51 61
11 10 16 24 40 51 61 12
10 16 24 40 51 61 12 12
16 24 40 51 61 12 12 14
24 40 51 61 12 12 14 19
40 51 61 12 12 14 19 976
51 61 12 12 14 19 976 8
61 12 12 14 19 976 8 980
Because we're reading from stdin, we can not do simple things like:
read/parse the first to determine number of columns
rewind file
read/parse all lines and store in matrix (allocating space as we go)
Note that using sqrt on the count to get number of rows/columns is a bit "unique". This is the first time I've seen that done.
When handling a 2D matrix that has dynamic dimensions, it helps to define a control struct to be able to store the dimensions. Then, all relevant info for the matrix is available to everyone.
In general, I really prefer fgets/strtok/strtol over scanf.
In this use case, I'm not sure if scanf("%d,",&val) can parse both (e.g.) 103, and 99. That is, the last number of the input file has no comma after it.
So, I had to refactor the code quite a bit. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
// matrix control
typedef struct {
int mtx_cols; // number of columns
int mtx_rows; // number of rows (input lines)
int *mtx_base; // pointer to matrix data
} mtx_t;
// helper macro to access a given matrix coordinate
#define MTX(_mtx,_irow,_icol) \
_mtx->mtx_base[((_irow) * _mtx->mtx_cols) + _icol]
// newMatrix -- get new matrix control
mtx_t *
newMatrix(void)
{
mtx_t *mtx;
mtx = calloc(1,sizeof(*mtx));
return mtx;
}
// readMatrix -- read in matrix from stream
void
readMatrix(mtx_t *mtx,FILE *xfin)
{
char *bp;
char *cp;
char buf[1000];
// get first line as a special case to calculate the number of columns
fgets(buf,sizeof(buf),xfin);
// we need to preserve the original data for the second loop below
char tmp[1000];
strcpy(tmp,buf);
// calculate number of columns
bp = tmp;
while (1) {
char *cp = strtok(bp," ,\n");
bp = NULL;
if (cp == NULL)
break;
mtx->mtx_cols += 1;
}
// read in row by row
while (1) {
// get current row index and advance the row count
int irow = mtx->mtx_rows++;
dbgprt("BUF/%d: %s",irow,buf);
// add space for this row
mtx->mtx_base = realloc(mtx->mtx_base,
sizeof(*mtx->mtx_base) * mtx->mtx_rows * mtx->mtx_cols);
if (mtx->mtx_base == NULL) {
perror("realloc");
exit(2);
}
// parse this row
bp = buf;
for (int icol = 0; icol < mtx->mtx_cols; ++icol) {
char *cp = strtok(bp," ,\n");
bp = NULL;
if (cp == NULL)
break;
MTX(mtx,irow,icol) = strtol(cp,&cp,10);
dbgprt(" %d\n",MTX(mtx,irow,icol));
}
// get data for next row
if (fgets(buf,sizeof(buf),xfin) == NULL)
break;
}
}
void
printMatrix(const mtx_t *mtx)
{
printf("\nMATRIX A:\n");
for (int irow = 0; irow < mtx->mtx_rows; ++irow) {
for (int icol = 0; icol < mtx->mtx_cols; ++icol)
printf(" %d",MTX(mtx,irow,icol));
printf("\n");
}
}
int
main(int argc,char **argv)
{
--argc;
++argv;
FILE *xfin;
if (argc > 0)
xfin = fopen(*argv,"r");
else
xfin = stdin;
if (xfin == NULL)
exit(1);
// declare 1D array and allocate memory
mtx_t *mtx = newMatrix();
readMatrix(mtx,xfin);
printMatrix(mtx);
return 0;
}

How to make parameter of double dimension arrangement to use in function

#include <stdio.h>
void Turn(int(*ptr)[4], int length, int vertical)
{
int arr[100][100] = { 0, };
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
arr[i][j] = *(*(ptr + (vertical - j - 1)) + i);
}
}
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
*(*(ptr + i) + j) = arr[i][j];
}
}
}
int main(void)
{
int BY[4][4] = {
1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16,
};
int length = sizeof(BY[0]) / sizeof(int);
int vertical = (sizeof(BY) / sizeof(int)) / length;
Turn(BY, length, vertical);
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
printf("%d ", BY[i][j]);
}
printf("\n");
}
return 0;
}
I wrote a function named Turn to rotate a 2D array right (a 90 degree rotation). I wanted to make this function to turn every array that has same vertical range and length. But I can't hand over
(I used google translate, I don't know how to describe it) parameter of a 2D array.
I first used void Turn(int(*ptr)[] ....)
but it didn't work. So I couldn't help using
int (*ptr)[4] in this function.
How can I make a parameter of a 2D array that can be used with any 2D array?
Using the C99 variable length array (VLA) feature make the problem easy. C11 makes support for VLAs optional, but the implementation must define __STDC_NO_VLA__ to show that it doesn't support VLAs.
Here's one version of the code. I've renamed your Turn() function (which turns the matrix 90° right into TurnR() and added a TurnL() function which turns the matrix 90° left. Because the code handles non-square matrices, the output matrix is separate from the input matrix. (You can simplify the code slightly if you only want to work with square matrices.)
#include <stdio.h>
static void TurnR(size_t rows, size_t cols, int matrix[rows][cols], int result[cols][rows])
{
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
result[c][rows - 1 - r] = matrix[r][c];
}
}
static void TurnL(size_t rows, size_t cols, int matrix[rows][cols], int result[cols][rows])
{
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
result[cols - 1 - c][r] = matrix[r][c];
}
}
static void Print(const char *tag, size_t rows, size_t cols, int matrix[rows][cols])
{
printf("%s (%zux%zu):\n", tag, rows, cols);
for (size_t r = 0; r < rows; r++)
{
const char *pad = "";
for (size_t c = 0; c < cols; c++)
{
printf("%s%3d", pad, matrix[r][c]);
pad = " ";
}
putchar('\n');
}
}
int main(void)
{
int BY[4][4] = {
{ 1, 2, 3, 4, },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12, },
{ 13, 14, 15, 16, },
};
int out[4][4];
Print("before", 4, 4, BY);
TurnR(4, 4, BY, out);
Print("right", 4, 4, out);
TurnL(4, 4, BY, out);
Print("left", 4, 4, out);
int m4x6[4][6] =
{
{ 1, 2, 3, 4, 5, 6, },
{ 7, 8, 9, 10, 11, 12, },
{ 13, 14, 15, 16, 17, 18, },
{ 19, 20, 21, 22, 23, 24, },
};
int m6x4[6][4];
Print("before", 4, 6, m4x6);
TurnR(4, 6, m4x6, m6x4);
Print("right", 6, 4, m6x4);
TurnL(4, 6, m4x6, m6x4);
Print("left", 6, 4, m6x4);
int m5x3[5][3] =
{
{ 1, 2, 3, },
{ 4, 5, 6, },
{ 7, 8, 9, },
{ 10, 11, 12, },
{ 13, 14, 15, },
};
int m3x5[3][5];
Print("before", 5, 3, m5x3);
TurnR(5, 3, m5x3, m3x5);
Print("right", 3, 5, m3x5);
TurnL(5, 3, m5x3, m3x5);
Print("left", 3, 5, m3x5);
TurnL(3, 5, m3x5, m5x3);
Print("doubleL", 5, 3, m5x3);
return 0;
}
And sample output is:
before (4x4):
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
right (4x4):
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
left (4x4):
4 8 12 16
3 7 11 15
2 6 10 14
1 5 9 13
before (4x6):
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
right (6x4):
19 13 7 1
20 14 8 2
21 15 9 3
22 16 10 4
23 17 11 5
24 18 12 6
left (6x4):
6 12 18 24
5 11 17 23
4 10 16 22
3 9 15 21
2 8 14 20
1 7 13 19
before (5x3):
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
right (3x5):
13 10 7 4 1
14 11 8 5 2
15 12 9 6 3
left (3x5):
3 6 9 12 15
2 5 8 11 14
1 4 7 10 13
doubleL (5x3):
15 14 13
12 11 10
9 8 7
6 5 4
3 2 1
I wouldn't dream of writing the code using the *(ptr + index) notation, especially with the double subscripts; it is just too error prone and hard to read (a nightmare, indeed!).

shifting a sequence of numbers in C?

I have a question about some trying to wrap around a sequence of numbers that I'm trying to shift in the C programming language. The first value that is found in the sequence of numbers I calculate via a loop gets thrown out in the end. Here is what the code looks like right now:
numbers[d] = numbers[x];
for (d = y-1; d >=0; d --){
numbers[d] = numbers[(d - 1) % y];
printf(" numbers[d] = %d \n", numbers[d]);
}
Here are the numbers[x] I calculated from my previous loop:
1, 17, 3, 15, 14, 6, 12, 8, 10
Here is what the numbers[d] currently looks like:
17, 3, 15, 14, 6, 12, 8, 10, 10
...and here is what it should look like:
17, 3, 15, 14, 6, 12, 8, 10, 1
It seems like it doesn't wrap the 1 around to the end. Is there a conditional that I am missing in my loop? Thanks!
Let's analyze your for loop, minus the printf statement.
for (d = y-1; d >=0; d --){
numbers[d] = numbers[(d - 1) % y];
}
Before you start the loop, you have the following values in numbers.
1, 17, 3, 15, 14, 6, 12, 8, 10
The value of y is 9.
In the first iteration of the loop, d = 8. (d-1)%y = 7. You replace the value of number[8] by number[7]. The array becomes:
1, 17, 3, 15, 14, 6, 12, 8, 8
In the next iteration of the loop, d = 7. (d-1)%y = 6. You replace the value of number[7] by number[6]. The array becomes:
1, 17, 3, 15, 14, 6, 12, 12, 8
When you reach the iteration where d=1, (d-1)%y = 0. You replace the value of number[1] by number[0]. The array becomes:
1, 1, 17, 3, 15, 14, 6, 12, 8
In the next iteration, d=0, (d-1)%y = -1. The statement
numbers[d] = numbers[(d - 1) % y];
is equivalent to
numbers[0] = numbers[-1];
This certainly leads to undefined behavior but it doesn't explain the other numbers in your output. Maybe the output that you posted corresponds to a different block of code.
I think the answer by #JonathanLeffler gives a solution to your algorithmic problem. I won't repeat that here.
Code
#include <stdio.h>
static const int debug = 0;
static void dump_array(const char *tag, int n, const int array[n])
{
printf("%s (%d)", tag, n);
for (int i = 0; i < n; i++)
printf("%3d", array[i]);
putchar('\n');
}
static void rot1u(int n, int numbers[n])
{
int v = numbers[n-1];
for (int d = n - 1; d >= 0; d--)
{
numbers[d] = numbers[(n + d - 1) % n];
if (debug)
printf(" numbers[%d] = %d\n", d, numbers[d]);
}
numbers[0] = v;
dump_array("Up After: ", n, numbers);
}
static void rot1d(int n, int numbers[n])
{
int v = numbers[0];
for (int d = 0; d < n; d++)
{
numbers[d] = numbers[(d + 1) % n];
if (debug)
printf(" numbers[%d] = %d\n", d, numbers[d]);
}
numbers[n-1] = v;
dump_array("Dn After: ", n, numbers);
}
int main(void)
{
int numbers[] = { 1, 17, 3, 15, 14, 6, 12, 8, 10 };
enum { N_NUMBERS = sizeof(numbers) / sizeof(numbers[0]) };
dump_array("-- Before:", N_NUMBERS, numbers);
rot1u(N_NUMBERS, numbers);
rot1d(N_NUMBERS, numbers);
rot1d(N_NUMBERS, numbers);
rot1d(N_NUMBERS, numbers);
rot1u(N_NUMBERS, numbers);
rot1u(N_NUMBERS, numbers);
return 0;
}
Example output
-- Before: (9) 1 17 3 15 14 6 12 8 10
Up After: (9) 10 1 17 3 15 14 6 12 8
Dn After: (9) 1 17 3 15 14 6 12 8 10
Dn After: (9) 17 3 15 14 6 12 8 10 1
Dn After: (9) 3 15 14 6 12 8 10 1 17
Up After: (9) 17 3 15 14 6 12 8 10 1
Up After: (9) 1 17 3 15 14 6 12 8 10
You need to save the element(s) which should be rotated to the the other side before the loop, and only put it into its proper place (theem into their proper places) afterwards.
#include <stdio.h>
#include <time.h>
#define METHOD 2
#define MAX_SKIERS 20
int starting_lineup[MAX_SKIERS+1];
int main(void)
{
int i, num_skiers = 20;
srand(time(NULL));
int pos1, pos2, temp;
for (i = 0; i <= num_skiers; i++)
starting_lineup[i] = i;
for (i = 0; i < num_skiers*2; i++) {
// Generate two random positions
pos1 = rand() % num_skiers + 1;
pos2 = rand() % num_skiers + 1;
// Swap the skiers at the two positions
temp = starting_lineup[pos1];
starting_lineup[pos1] = starting_lineup[pos2];
starting_lineup[pos2] = temp;
}
printf("The starting lineup (first to last):\n");
for (i = 1; i <= num_skiers; i++)
printf("%s%d", (i == 1 ? "" : ", "), starting_lineup[i]);
putchar('\n');
return 0;
}

Sorting 2-dimensional array in ANSI C with qsort()

I have a two dimensional array and want to sort both rows depending on the order of the elements in the first row:
i start with:
row1: { 4, 3, 1, 5, 0}
row2: { 7, 8, 9, 1, 2}
and the result should be:
row1: { 0, 1, 3, 4, 5}
row2: { 2, 9, 8, 7, 1}
QUESTION:
Is it possible to achieve this, by using the qsort() function?
I think ,that way it could be done.
#include<bits/stdc++.h>
using namespace std;
int cmp(const void *a,const void *b) {
return ((const int *)a)[0] - ((const int *)b)[0];
}
int main(int argc,char *argv[]){
int list[10][2];
printf("Before sorting\n");
for(int i=0; i<10; i++){
list[i][0] = rand()%31;
list[i][1] = rand()%12;
printf ("list[%d][0] = %d list[%d][1] = %d\n", i, list[i][0], i, list[i][1]);
}
printf("AFTER sorting\n");
qsort(list,10,2*sizeof(int),cmp);
for(int i=0; i<10; i++)
printf ("list[%d][0] = %d list[%d][1] = %d\n", i, list[i][0], i, list[i][1]);
return 0;
}
Output :
Before sorting
list[0][0] = 10 list[0][1] = 11
list[1][0] = 10 list[1][1] = 4
list[2][0] = 11 list[2][1] = 4
list[3][0] = 8 list[3][1] = 6
list[4][0] = 23 list[4][1] = 8
list[5][0] = 1 list[5][1] = 5
list[6][0] = 0 list[6][1] = 3
list[7][0] = 10 list[7][1] = 11
list[8][0] = 19 list[8][1] = 2
list[9][0] = 22 list[9][1] = 0
AFTER sorting
list[0][0] = 0 list[0][1] = 3
list[1][0] = 1 list[1][1] = 5
list[2][0] = 8 list[2][1] = 6
list[3][0] = 10 list[3][1] = 11
list[4][0] = 10 list[4][1] = 4
list[5][0] = 10 list[5][1] = 11
list[6][0] = 11 list[6][1] = 4
list[7][0] = 19 list[7][1] = 2
list[8][0] = 22 list[8][1] = 0
list[9][0] = 23 list[9][1] = 8
Not directly ...
... but qsort() could sort vectors by each vector's first element.
So the example data needed to be transposed and be converted into a fake 2d array, where the root pointer points to an array of pointers, with each pointer pointing to a row of the transposed original data.
qsort() then is passed the root pointer and the compare function compares on the vectors' first element. The vectors are passed to compare function by reference.
After sorting is done the result then needs to be converted the revers way as done prior to the call to qsort().

Resources