Matrix Rotation
Understand the implementation of clockwise and counterclockwise matrix rotations.
We'll cover the following
In this lesson, we’ll learn about rotating matrices by 90 degrees in both clockwise and counterclockwise directions. To grasp the essence of matrix rotation, we’ll begin by visualizing the concept, allowing us to better comprehend the transformations involved. Subsequently, we’ll proceed to the implementation stage, where we’ll implement and understand the code for clockwise matrix rotation.
Here’s the exercise playground where you’ll write your implementation following the guidance provided after the playground.
Exercise playground
4 2 2 1 2 4 5 2 3 1 2 3 4 5 4 2 2 1 2 4 5 5 3 4 6 5 3 3 4 5 8 9 4 5 3 7 2 3
Implementation of the clockwise matrix rotation
Let’s discuss two implementations.
Implementation 1: Clockwise matrix rotation (using extra matrix and reordering it)
╔═══════════╦═══════════╗║ Original ║ Rotated ║╠═══════════╬═══════════╣║ 1 2 3 ║ 7 4 1 ║║ 4 5 6 ║ 8 5 2 ║║ 7 8 9 ║ 9 6 3 ║╚═══════════╩═══════════╝
Notice the following:
Each column becomes a row. For example, the first column is the first row, the second column is the second row, and so on.
Each column is in reverse order. So, for each element at the position
(r, c)
in the original matrix, it is placed at the position(c, Rows-1-r)
in the rotated matrix.
Let’s look at the implementation:
const Matrix Matrix::RotateCW()const // We have deliberately implemented RotateCW() in-place{Matrix cycle(this->cols, this->rows);for (int r = 0; r <this->rows; r++){for (int c = 0; c < this->cols; c++){cycle.Vs[c][cycle.rows - 1 - r] = this->Vs[r][c];}}return cycle;}const Matrix Matrix::RotateCWMulti(const int multiple)const{if (multiple % 90 != 0){cout << "Not a multiple of 90 entered, returning the original matrix. Press any key to continue" << endl;//getch();return*this;}Matrix result = *this;int cycles = multiple / 90;for (int i = 1; i <=cycles; i++){result = result.RotateCW();}return result;}
-
Lines 1–11: The first function,
Matrix::RotateCW()
, rotates the matrix by 90 degrees in a clockwise direction. It creates a new matrix calledcycle
with swapped dimensions, representing the rotated matrix. Using nested loops, it iterates over each element of the original matrix and assigns the corresponding element to its rotated position in thecycle
matrix. Finally, it returns thecycle
(the rotated matrix). -
Lines 13–28: The second function,
Matrix::RotateCWMulti(const int multiple)
, allows rotating the matrix by a multiple of 90 degrees. It checks if the provided value formultiple
is a multiple of 90 degrees. If not, it displays an error message and returns the original matrix. Ifmultiple
is a multiple of 90 degrees, it initializes theresult
matrix as a copy of the original matrix. Then, it determines the number of cycles needed for the rotation. Using a loop, it performs the rotation by repeatedly calling theRotateCW()
function and updating theresult
matrix. After the loop, the final rotated matrixresult
is returned.
Implementation 2: Using transpose as a subroutine
To tackle this problem, we’ve broken it down into three distinct steps for better implementation:
We initialize a
matrix. This part is already implemented in the main()
function.We reverse each column of the matrix individually.
Finally, we obtain the transpose of the modified matrix.
Each step is visually depicted below to provide a clearer understanding of the concept at hand:
Here’s our second implementation:
int Matrix::reverseEveryColumn(){for (int c = 0; c < this->cols; c++) // for each column c{for (int r = 0; r <this->rows/2-1; r++) // for each element in the upper half column{swap(this->Vs[r][c], this->Vs[this->rows-1-r][c]); // swap with lower one}}}const Matrix Matrix::RotateCW()const{reverseEveryColumn();*this = !(*this); // transposereturn *this; // We have deliberately implemented RotateCW() in-place}
Includes two functions related to matrix operations.
Lines 1–10: The first function,
Matrix::reverseEveryColumn()
, reverses the elements in each column of the matrix. It iterates over each columnc
and, using a nested loop, swaps the elements in the upper half of the column with their corresponding elements in the lower half of the column.Lines 11–16: The second function,
Matrix::RotateCW()
, rotates the matrix clockwise by 90 degrees. It first calls thereverseEveryColumn()
function to reverse the elements in each column. Then, it performs a matrix transpose operation by using the overloaded!
operator on the matrix i.e.,*this = !(*this)
. Finally, it returns the modified matrix. It is important to note that the implementation of theRotateCW()
function is done in place, meaning that the original matrix is modified rather than creating a new matrix for the rotated result.
Exercise: Matrix rotation counterclockwise
This exercise is here to give you an opportunity to practice. Implement the code to reindex the population of a counterclockwise matrix.
Implementation 1: Counterclockwise matrix rotation
You need to create the following two functions:
-
The
RotateACW()
function that rotates the matrix counterclockwise by 90 degrees, -
And the
RotateACWMulti()
function that extends this capability to rotate the matrix by a multiple of 90 degrees in a counterclockwise direction.
Write your own code in the Exercise playground. If you have trouble getting to the solution, you can click the “Show solution” button to see how to implement it.
Implementation 2: Using transpose
Similar to the second implementation done in the clockwise case, here’s the observation:
We’ve broken it down into three distinct steps for better understanding and implementation:
We initialize a
matrix. This part is already implemented in the main()
function.Next, we reverse each row of the matrix individually.
Finally, we obtain the transpose of the modified matrix.
Each step is visually depicted below to provide a clearer understanding of this concept.
Assigning operators to clockwise/counterclockwise rotations
Now that we have implemented the two functions, we can easily make our own two user-defined operators for our Matrix
class with the following two prototypes (defined in Matrix.h
):
const Matrix operator>(int clockwiseAngle)const; // ClockwiseAngle: multiple of 90const Matrix operator<(int counterClockwiseAngle)const; // counterClockwiseAngle: multiple of 90
Their implementation will be the following:
const Matrix Matrix::operator>(int clockwiseAngle)const // ClockwiseAngle: multiple of 90{return RotateCWMulti(clockwiseAngle);}const Matrix Matrix::operator<(int counterClockwiseAngle)const // counterClockwiseAngle: multiple of 90{return RotateACWMulti(counterClockwiseAngle);}
Notice that we have already implemented the operator >()
and operator <()
functions, but these operators are different because the arguments passed to these operators are different from the ones we implemented in the previous lesson for adding comparison operators (for a matrix search as a subset).
Tip: Write these two operator
Matrix.cpp
andoperator <()
, in theMatrix.cpp
file in the Exercise playground.