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

#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!).

Related

qsort struct not doing as supposed to

Hi so I'm trying to sort my struct with qsort and it sort of works but not really...
Can anyone tell me what's happening and why it goes wrong ? :)
#include <stdio.h>
#include <stdlib.h>
int el_cmp(const void *ep1, const void *ep2);
typedef struct kort
{
int kuloer;
int vaerdi;
} kort;
int main(void){
int i;
int k[] = {3, 4, 5, 6};
int v[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
kort kort[52];
for (i = 0; i < 52; i++){
kort[i].kuloer = k[i % 4];
kort[i].vaerdi = v[i % 13];
}
printf("\n");
qsort(kort, 52, sizeof(int), el_cmp);
for (i = 0; i < 52; i++){
printf("Kort%d: %d %d\n", i + 1, kort[i].kuloer, kort[i].vaerdi);
}
return(0);
}
int el_cmp(const void *ep1, const void *ep2){
int *tp1 = (int*) ep1,
*tp2 = (int*) ep2;
if (*tp1 < *tp2){
return -1;
} else if (*tp1 > *tp2){
return 1;
} else return 0;
}
the result is this:
Kort1: 2 2
Kort2: 3 3
Kort3: 3 3
Kort4: 3 3
...
Kort5: 3 3,
Kort6: 3 4,
Kort7: 4 4,
Kort8: 4 4,
Kort9: 4 4,
Kort10: 4 4,
Kort11: 5 5,
Kort12: 5 5,
Kort13: 5 5,
Kort14: 5 5,
Kort15: 6 6,
Kort16: 6 6
Kort17: 6 6,
Kort18: 6 6,
Kort19: 7 7,
Kort20: 8 8,
Kort21: 9 9,
Kort22: 10 10,
Kort23: 11 11,
Kort24: 12 12,
Kort25: 13 13,
Kort26: 14 14,
Kort27: 5 2
Kort28: 6 3
Kort29: 3 4
...
Kort30: 4 5,
Kort31: 5 6,
Kort32: 6 7,
Kort33: 3 8,
Kort34: 4 9,
Kort35: 5 10,
Kort36: 6 11,
Kort37: 3 12,
Kort38: 4 13,
Kort39: 5 14,
Kort40: 6 2,
Kort41: 3 3,
Kort42: 4 4,
Kort43: 5 5,
Kort44: 6 6,
Kort45: 3 7,
Kort46: 4 8,
Kort47: 5 9,
Kort48: 6 10,
Kort49: 3 11,
Kort50: 4 12,
Kort51: 5 13,
Kort52: 6 14,
but I'm expecting this:
Kort1: 3 2
Kort2: 3 3
Kort3: 3 4
Kort4: 3 5
...
Kort5: 3 6,
Kort6: 3 7,
Kort7: 3 8,
Kort8: 3 9,
Kort9: 3 10,
Kort10: 3 11,
Kort11: 3 12,
Kort12: 3 13,
Kort13: 3 14,
Kort14: 4 2
Kort15: 4 3
...
Kort16: 4 4,
Kort17: 4 5,
Kort18: 4 6,
Kort19: 4 7,
Kort20: 4 8,
Kort21: 4 9,
Kort22: 4 10,
Kort23: 4 11,
Kort24: 4 12,
Kort25: 4 13,
Kort26: 4 14,
...
Kort27: 5 2,
Kort28: 5 3,
Kort29: 5 4,
Kort30: 5 5,
Kort31: 5 6,
Kort32: 5 7,
Kort33: 5 8,
Kort34: 5 9,
Kort35: 5 10,
Kort36: 5 11,
Kort37: 5 12,
Kort38: 5 13,
Kort39: 5 14,
...
Kort40: 6 2,
Kort41: 6 3,
Kort42: 6 4,
Kort43: 6 5,
Kort44: 6 6,
Kort45: 6 7,
Kort46: 6 8,
Kort47: 6 9,
Kort48: 6 10,
Kort49: 6 11,
Kort50: 6 12,
Kort51: 6 13,
Kort52: 6 14,
For starters it is a bad idea to redeclare the name kort
kort kort[52];
Nevertheless this call of qsort
qsort(kort, 52, sizeof(int), el_cmp);
is incorrect. You have an array of structures of the type struct kort not of the type int. The call of qsort can look the following way
qsort(kort, sizeof( kort ) / sizeof( *kort ), sizeof( *kort ), el_cmp);
The comparison function can look the following way
int el_cmp( const void *ep1, const void *ep2 )
{
const struct kort *a = ep1;
const struct kort *b = ep2;
int result = ( b->kuloer < a->kuloer ) - ( a->kuloer < b->kuloer );
if ( result == 0 )
{
result = ( b->vaerdi < a->vaerdi ) - ( a->vaerdi < b->vaerdi );
}
return result;
}
Here is your updated program.
#include <stdio.h>
#include <stdlib.h>
typedef struct kort
{
int kuloer;
int vaerdi;
} kort;
int el_cmp( const void *ep1, const void *ep2 )
{
const struct kort *a = ep1;
const struct kort *b = ep2;
int result = ( b->kuloer < a->kuloer ) - ( a->kuloer < b->kuloer );
if (result == 0)
{
result = ( b->vaerdi < a->vaerdi ) - ( a->vaerdi < b->vaerdi );
}
return result;
}
int main( void )
{
int k[] = { 3, 4, 5, 6 };
int v[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
const size_t k_size = sizeof( k ) / sizeof( *k );
const size_t v_size = sizeof( v ) / sizeof( *v );
enum { N = 52 };
kort kort[N];
for ( size_t i = 0; i < N; i++ )
{
kort[i].kuloer = k[i % k_size];
kort[i].vaerdi = v[i % v_size];
}
qsort( kort, N, sizeof( *kort ), el_cmp );
for ( size_t i = 0; i < N; i++ )
{
printf( "Kort%zu: %d %d\n", i + 1, kort[i].kuloer, kort[i].vaerdi );
}
putchar( '\n' );
}
The program output is the same as you are expecting
Kort1: 3 2
Kort2: 3 3
Kort3: 3 4
Kort4: 3 5
Kort5: 3 6
Kort6: 3 7
Kort7: 3 8
Kort8: 3 9
Kort9: 3 10
Kort10: 3 11
Kort11: 3 12
Kort12: 3 13
Kort13: 3 14
Kort14: 4 2
Kort15: 4 3
Kort16: 4 4
Kort17: 4 5
Kort18: 4 6
Kort19: 4 7
Kort20: 4 8
Kort21: 4 9
Kort22: 4 10
Kort23: 4 11
Kort24: 4 12
Kort25: 4 13
Kort26: 4 14
//...

Populating and array in a matrix style

I want to populate an array in a matrix style, on columns. So for example, if I had an array input:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Then the matrix would be (for numRows = 3, numCols=5):
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
This means the real array would be:
1 4 7 10 13 2 5 8 11 14 3 6 9 12 15
How would I do that?
Here is my take:
int v[15] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int matrix[15];
int row = 0, col = 0;
for (int i = 0; i < 15; ++i) {
matrix[col * 5 + row] = v[i];
printf("row = %d col = %d\n", row, col);
row++;
if (row == 3) {
row = 0;
col++;
}
}
```
You were very close in your last code example. The short answer is that rather than this:
matrix[col * 5 + row] = v[i];
You want:
matrix[row * 5 + col] = v[i];
In other words, 'row' and 'col' need to be the other way around.
Here's your example with that change made, and the results printed at the end:
int main(int argc, const char * argv[]) {
int v[15] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int matrix[15];
int row = 0, col = 0;
for (int i = 0; i < 15; ++i) {
matrix[row * 5 + col] = v[i];
printf("row = %d col = %d\n", row, col);
row++;
if (row == 3) {
row = 0;
col++;
}
}
for (int i = 0; i < 15; ++i) {
printf("%d ", matrix[i]);
}
printf("\n");
}
The output at the end for me is:
1 4 7 10 13 2 5 8 11 14 3 6 9 12 15
Which appears to match the output you were after in your post.
There are multiple conversions that can be made here: from 2-d row/column indices to 1-d indices in row- or column-major order, and from 1-d indices in row- or column-major order to 2-d row/column indices. The math is fairly simple for all the conversions (converting from 1-d to 2-d indices involves integer division and modulus). Once you figure out the conversions you need, I suggest creating a little library of functions for performing the conversions so that you have the functionality available when you need it.
Lastly, a couple general suggestions. Your original code wrote outside array bounds, which wasn't checked for, at least in what you posted. For exploratory work like this, I'd suggest using bounds checking so that you can detect errors more easily. (For example, in this case you could use std::array and the at() function.) This will help you catch a certain class of mistakes early.
I'd also suggest using named constants, even in a small example like this, e.g. 'numRows' and 'numCols' instead of 3 and 5, and 'numElements' as the product of those instead of 15. This will also help avoid errors, and will also make the code easier to read and understand (both for you and others).

Printing 2D array diagonally right-down

Trying to print a 2D array diagonally, going right to down, other solutions I've found are going in the opposite direction
Example of what I'm trying to achieve:
Input:
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
Intended Output:
0 2 4 6
1 3 5
2 4
3
(and other side 1 3 5, 2 4, 3)
Managed to print a diagonal with
for (x=0; x<12; x++) {
printf("%d ", arr[x][x])
}
But unsure how to replicate it for multiple, following attempt is incorrect
for (x=0; x<12; x++) {
for (y=0;y<x+1;y++) {
printf("%d ", arr[x][y]);
}
printf("\n");
}
The following C program meets your requirements. Try to understand the indexing.
int n, i, j, k;
int arr[5][5] = {
0, 1, 2, 3, 4,
1, 2, 3, 4, 5,
2, 3, 4, 5, 6,
3, 4, 5, 6, 7,
4, 5, 6, 7, 8
};
n = 5;
for (k = 0; k < n; k++) {
int ind = 0;
for (i = k; i < n; i++) {
printf("%d ", arr[i][ind++]);
}
printf("\n");
}
Output of the following program:
0 2 4 6 8
1 3 5 7
2 4 6
3 5
4
You can change the size of the array and change the value of n, it will work for your desired n*n array.

How to rearrange a two dimensional array

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.

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;
}

Resources