shift matrix columns in c - c

how can i shift each column of a matrix to the left by the row number ?
for example
0, 1, 2, 3
4, 5, 6, 7
8, 9,10,11
12,13,14,15
this is a 4*4 matrix, the index of the first row is 0, therefore the columns will not move,
the second row's index is 1, therefore each column will move 1 spot to the left (cyclically).
the output for the given matrix is
example
my function code is:
void ShiftRows(int message[M][M])
{
int temp = 0;
for (int i = 1; i < M ; i++)
{
for (int j = 0; j < M; j++)
{
temp = message[i][(j-i)%M];
message[i][(j-i)%M] = message[i][j];
message[i][j] = temp;
}
temp = 0;
}
}

You only swap 2 values. That does not work for cyclically shift a whole row.
void ShiftRows(int message[M][M])
{
for (int i = 1; i < M ; i++)
{
int temp[M];
// First shift using a copy
for (int j = 0; j < M; j++)
{
temp[j] = message[i][(j+i)%M];
}
// After whole row is shifted, copy back
for (int j = 0; j < M; j++)
{
message[i][j] = temp[j];
}
}
}

Related

What am i doing wrong in this loop

#include <stdio.h>
#define ROWS 2
#define COLS 5
int main(void)
{
unsigned int rooms[ROWS][COLS] = {0}, selection, building, room;
int i, j;
for(i = 0; i < ROWS; i++)
{
for(j = 0; j < COLS; j++)
{
if(rooms[i][j] == 0)
{
rooms[i][j] = 1;
printf("\nBuilding[%.2d]|Room[%.2d]: Reservation Succesfull.\n\n", i + 1, j + 1);
break;
}
}
}
return 0;
}
Note that this is not the full code and i only have a problem with this part.
What i want here is to check the first 0 that comes first and turn it into a 1. This will happen until all the 0 become 1 or until the user exits the program. I already made a "do while" for that. My problem is that when i run this part of the program it puts 1 both on ROWS 0 and ROWS 1 at the same time. I'm looking for why is this happening more than an answer to fix the program.
I made some tests like putting another if for the first loop(i) but that either resulted in the same problem or the whole ROWS 1 was skipped and only the ROWS 0 was filled.
It is because the break statement just gets out of the first outer loop, it seems like you also want to skip the other outer one. You may need to add a flag to check only one 0 element will be changed to 1, or just change break into return to get out of the function as it is said on the comments.
int flag = 0;
for(i = 0; i < ROWS; i++)
{
for(j = 0; j < COLS; j++)
{
if(rooms[i][j] == 0)
{
flag = 1;
rooms[i][j] = 1;
printf("\nBuilding[%.2d]|Room[%.2d]: Reservation Succesfull.\n\n", i + 1, j + 1);
break;
}
}
if(flag == 1)
{
break;
}
}
Or with a clear explicit initialization of the matrix,
void func(void)
{
unsigned int rooms[ROWS][COLS] = {
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
}, selection, building, room;
int i, j;
for(i = 0; i < ROWS; i++)
{
for(j = 0; j < COLS; j++)
{
if(rooms[i][j] == 0)
{
rooms[i][j] = 1;
printf("\nBuilding[%.2d]|Room[%.2d]: Reservation Succesfull.\n\n", i + 1, j + 1);
return;
}
}
}
}

How to correctly implement an insertion sort algorithm in a 2D array?

I need to sort the columns of my 2D array based on the first row of the array. This is my 2d array before sorting:
cargo
AFADA
DAFGF
DXAFA
DDFFX
GFXF
and this is the image of my 2D array:
acrgo
FAADA
ADFGF
XDAFA
DDFFX
FGXF
The correct output looks like this
acgor
FADAA
ADGFF
XDFAA
DDFXF
FGF X
. This is the code of my function to sort the array using insertion sort algorithm
void sort(char** newTable, int row, int col) {
for (int top = 1; top < col; col++) {
char item = newTable[0][top];
int i = top;
while (i > 0 && item < newTable[0][i - 1]) {
for (int j = 0; j < row + 1; j++) {
char temp = newTable[j][i];
newTable[j][i] = newTable[j][i - 1];
newTable[j][i - 1] = temp;
}
i--;
}
newTable[0][i] = item;
}
}
I called the function like this
sort(newTable, row, strlen(key));
here, key is the string 'cargo'
The definition of newTable:
char** newTable = (char**)calloc(row + 1, sizeof(char*));
for (int i = 0; i < row + 1; i++) {
newTable[i] = (char*)calloc(strlen(key), sizeof(char));
}
newTable is indeed an array of pointers and not a 2D array, so using char **newTable makes sense.
The major error is close to a typo: in the first for loop of sort, you increment col when you want to increment top. And the last line newTable[0][i] = item; is useless.
This should work (even if the loop for (int j = 0; j < row + 1; j++) suggests that row is not the number of rows in newTable but only the number of *additional rows):
void sort(char** newTable, int row, int col) {
for (int top = 1; top < col; top++) {
char item = newTable[0][top];
int i = top;
while (i > 0 && item < newTable[0][i - 1]) {
for (int j = 0; j < row + 1; j++) {
char temp = newTable[j][i];
newTable[j][i] = newTable[j][i - 1];
newTable[j][i - 1] = temp;
}
i--;
}
}
}

C - Nested loops and stack?

I am trying to find the location of a target inside of a 1-D array that acts like a table with rows and cols. I could do it using divide and mod, but I am stuck on finding it using nested loops. specifically, I can't seem to assign values inside the nested loop.
here is my code:
#include <stdio.h>
int main()
{
int arr[9] = // act as a 3 X 3 table
{ 2, 34, 6,
7, 45, 45,
35,65, 2
};
int target = 7;// r = 1; c = 0
int r = 0; // row of the target
int c = 0; // col of the target
int rows = 3;
int cols = 3;
for (int i = 0; i < rows; i++){
for (int j = 0; j + i * cols < cols + i * cols; i++ ){
if (arr[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
}
printf ("%d, %d",c, r);
return 0;
}
The code outputs: 0,0.
The problem isn't with the assignment, it's with the wrong loop and if condition.
The outer loop should loop over the i rows
The inner loop should loop over the j columns
within both loops, the cell to evaluate is i * cols + j
Put it all together and you'll get:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++ ) {
if (arr[i * cols + j] == target) {
c = j; // columns of the target
r = i; // rows of the target
}
}
}
Since arr is 1D array and inside for loop, for any i value j will reach upto max 3 only so its not checking after arr[3]
To avoid this problem take int pointer and points to arr and do the operation as below
int *p = arr;
for (i = 0; i < rows; i++){
for ( j = 0; j < cols ; j++ ){
if (p[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
p = p + j;/*make p to points to next row */
}
A better solution would use only one loop:
for (int i = 0; i < rows * cols; i++){
if (arr[i] == target){
r = i / 3;
c = i % r;
}
}

Array element disappears

I'm trying to track a player's location with x marking their spot. When the player enters a string I increment the coordinates accordingly. However when the player is located one space from the perimeter, then attempts to move to the edge of the map, the player disappears.
Example:
.....
...x.
.....
.....
.....
Player located at 'x'
If player enters string "right" and I move player_loc, array simply returns:
.....
.....
.....
.....
.....
I attempted to add a sort of buffer by increasing the size of the array. No luck. I've been stuck on this for almost a week now. Any help would be appreciated. I apologize for messy code. I'm a total newbie at this and I'm really just futzing around in the dark with all this stuff. I've researched this across the forums here and haven't found a solution. If you know of something that I possibly (probably) missed feel free to point me in that direction.
#include <stdio.h>
#include <string.h>
char map[6][6];
char player_loc = 'x';
int row;
int col;
void init_map()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
map[i][j] = '.';
}
}
}
void print_map()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
}
int get_player_loc()
{
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
if(map[j][k] == player_loc)
{
row = k;
col = j;
}
}
}
return row;
return col;
}
void init_player_loc()
{
int check = 1;
for (int g = 0; g < 5; g++) {
for (int h = 0; h < 5; h++) {
if (map[g][h] == 'x') {
check = 0;
}
}
}
if(check == 1) {
map[0][0] = player_loc;
} else {
get_player_loc();
}
}
void move_left()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j-1] = player_loc;
map[i][j] = '.';
}
}
}
}
void move_right()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
}
}
}
}
int main(int argc, char* argv[])
{
char input[15];
printf("You enter a room...you can go left, right, or straight. Which way do you go?\n");
int done = 0;
init_map();
map[3][3] = player_loc;
//init_player_loc();
print_map();
while (!done) {
scanf("%s", input);
if (strcmp("left", input) == 0) {
move_left();
printf("You go left...\n");
print_map();
get_player_loc();
printf("%d %d\n", row, col);
done = 1;
}
else if (strcmp("right", input) == 0) {
move_right();
printf("You go right...\n");
print_map();
get_player_loc();
printf("%d %d\n", row, col);
done = 1;
}
else if (strcmp("straight", input) == 0) {
printf("You go straight...");
done = 1;
}
else {
printf("Sorry, can't do that.\n");
}
}
}
You must break the loop if you find the player location, e.g
void move_right()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
return;
}
}
}
}
In your code you move right the player, and the next loop will find the player in the new location and do the right move again, forever.
Moreover in your code you are not taking care of boundaries of your 2d matrix: j+1 is valid only if j<5.
Then a better code should be
void move_right()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
return;
}
}
}
}
The problem is that your move_right function picks up the player and moves them completely off of the map. Let's say your player is at [0, 2] and step through the code.
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
}
}
[0, 0] No player here, move along
[0, 1] No player here, move along
[0, 2] Found a player! Move them right to [0, 3]
[0, 3] Found a player! Move them right to [0, 4]
[0, 4] Found a player! Move them right to [0, 5]
At 5, the loop ends. Because of the buffer you added, your array is 6x6, so the player is stashed in the wings without crashing the program. There are a few things you should do:
Once you've found and moved the player, break or return so they'll only move once.
Make your array 5x5 (or print all 6x6) so you can see everything.
Do some bounds checking so the player isn't allowed to move right from j = 5.
Watch out for this same bug in move_up, where it would happen as you increment i.
Your loops allow for checking the position twice, once at i,j, and again at i,(j+1) (or some other variant). This probably isn't what you intend. After you find the player you should make the updates and then break out of the loops.
Also, the code as is allows for indexing passed the bounds of the array, in theory. Also not what is desired. You may consider bounds checking. I don't know what is supposed to happen when the player moves right and there is a wall to the right. Does he not move? Wrap around? LR corner could cause seg fault as it is now.
You appear to have row and column indeces transposed in the get_player_loc function, as well as having two return statements (the compiler should warn you about unreachable code), neither of which is required or used by the calling code.
At the start, initialise the row and col variables. (Values taken from your main.)
int row = 3;
int col = 3;
Change the get_player_loc function so that it just updates the globals row and col. It sets row and col to 0 if the player is not found, as per the original.
void get_player_loc(void)
{
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
if(map[j][k] == player_loc)
{
// The meaning of row and col is set by how they are used
// to index the array in the move and print functions. Keep
// the same order and meaning here.
row = j;
col = k;
return;
}
}
}
// Set row and col to 0 if the location is not found.
row = 0;
col = 0;
map[0][0] = player_loc;
}
You'll still have problems when they reach an edge, due to the index into the array going out of bounds in the move functions, but that's a different problem.

Function to left shift a 2D array in C

I'm writing a function within my program to left shift all the numbers in an array that was passed to the function. An example is:
1 2 3
4 5 6
becomes
2 3 4
5 6 1
My code is:
void LeftShift(int array[][N])/*Get the array from main*/
{
int r, c, temp;
for(r = 0; r < M; r++) { //Start at row 0 and add one each time
for(c = 0; c < N; c++) { //Start at column 0 and add one each time
if(c > 0) {
array[r][c] = array[r][c-1]; //Number is moved over one if its not the first column
}
else if(c == 0 && r > 0) { //If its first column but not first row
array[r][c] = array[r-1][N-1];//Move number up one row and too last column
}
else {
temp = array[r][c];//If its first column and first row store value in temp
}
}
}
array[M-1][N-1] = temp;//Put temp value at end of array
}
When I print this out all I get is the first number from the original array in every spot in the array. M is defined at the top to be 6 and N is defined to be 5. After this runs, I call a function that prints out the new array and all I get is the first value 30 times in an array.
2-D arrays are contiguous in memory, so you can iterate over it as if it were a 1-D array:
void left_rotate(int array[][N])
{
int *flat = (int *)array;
int temp = flat[0];
for ( size_t i = 1; i < M*N; ++i )
flat[i-1] = flat[i];
flat[M*N-1] = temp;
}
The for loop could also be replaced with a single block move:
memmove(&flat[0], &flat[1], (M*N-1) * sizeof *flat);
array[r][c] = array[r][c-1];
should be
array[r][c-1] = array[r][c];
Likewise for the row shift.
You can go throw the array, having a pointer following the last place you visited, and moving the elements, as in this example:
#define nrows 4
#define ncols 4
int array[nrows][ncols] = {
{ 1, 2, 3, 4, },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12, },
{ 13, 14, 15, 16, },
};
int main()
{
int row, col;
int saved_int;
int *p = &saved_int;
/* rotate elements */
for(row = 0; row < nrows; row++)
for (col = 0; col < ncols; col++) {
*p = array[row][col];
p = &array[row][col];
} /* for */
*p = saved_int;
/* print matrix */
for (row = 0; row < nrows; row++) {
for (col = 0; col < ncols; col++)
printf( "%s%d",
(col ? "\t" : ""),
array[row][col]);
printf("\n");
} /* for */
return 0;
} /* main */

Resources