my problem is to take a matrix mat of rowcol length, and move each column within it one position to the left. For example if i have a 3x3 matrix like this:
4 5 2
6 7 3
3 4 6
the result should must be like this:
5 2 4
7 3 6
4 6 3
I can't get the method to work, how many times I do it, does anyone have any ideas?
Below my code:
for(int i = rowcol - 1; i > 0; i--)
for(int j = 0; j < rowcol; j ) {
if(i == 0) swap(mat[j][rowcol - 1], mat[j][i]);
swap(mat[j][i], mat[j][i-1]);
}
CodePudding user response:
The standard library has an algorithm to do what you're asking: std::rotate
. The following example rotates everything right one column.
#include <iostream>
#include <algorithm>
int main()
{
int arr[][3] = {
{ 1,2,3 },
{ 4,5,6 },
{ 7,8,9 }
};
for (auto& row : arr)
{
std::rotate(row, row 2, row 3);
}
for (auto& row : arr)
{
for (auto x : row)
std::cout << x << ' ';
std::cout << '\n';
}
}
Output
3 1 2
6 4 5
9 7 8
Obviously the conditions of your matrix access to individual rows can be (and is likely) different than the above trivial example, but nonetheless, the concept is still the same. I leave it to you to play with for learning how to do it "left" (it won't be hard *).
hint: std::rotate(row, row 1, row 3);
CodePudding user response:
Here's my updated solution. It's even easier than the original one I posted a few minutes earlier.
Basically, for each row:
- Save off the value in the first column
- Shift all the values (starting at column 1) in the row by one to the left.
- The last value in the row is the previously saved variable from the first step
Code:
for (size_t row = 0; row < rowcol; row ) {
int tmp = mat[row][0];
for (size_t col = 1; col < rowcol; col ) {
mat[row][col-1] = mat[row][col];
}
mat[row][rowcol-1] = tmp;
}
CodePudding user response:
What about as follows ?
for ( auto ui = 0u ; ui < rowcol ; ui )
for ( auto uj = 1u ; uj < rowcol ; uj )
std::swap(mat[ui][uj-1], mat[ui][uj]);
The following is a full compiling example
#include <iostream>
static constexpr std::size_t rowcol = 3u;
void printMat (int mat[rowcol][rowcol])
{
for ( auto ui = 0u ; ui < rowcol ; ui ) {
for ( auto uj = 0u ; uj < rowcol ; uj )
std::cout << mat[ui][uj] << ' ';
std::cout << std::endl;
}
std::cout << std::endl;
}
int main()
{
int mat[rowcol][rowcol] { {4, 5, 2}, {6, 7, 3}, {3, 4, 6} };
printMat(mat);
for ( auto ui = 0u ; ui < rowcol ; ui )
for ( auto uj = 1u ; uj < rowcol ; uj )
std::swap(mat[ui][uj-1], mat[ui][uj]);
printMat(mat);
}
CodePudding user response:
Your logic is correct except, you're actually shifting the columns of the matrix one position to the right, not left. Not only that, the (i==0) condition is not required.
Replace the backward iteration with forward iteration and get rid of the conditional statement and you're good to go. Here's the modified code:
for(int i = 0; i < rowcol-1; i )
for(int j = 0; j < rowcol; j ) {
// if(i == 0) swap(mat[j][rowcol - 1], mat[j][i]);
swap(mat[j][i], mat[j][i 1]);
}
Basically your logic is similar to Bubble Sort. You were bubbling the final column towards the beginning of the matrix by shifting all other columns rightward.
I inverted it by making it so that we are bubbling the first column towards the end instead. Feel free to ask any questions.