Inspired by Raymond Chen's post, say you have a 4x4 two dimensional array, write a function that rotates it 90 degrees. Raymond links to a solution in pseudo code, but I'd like to see some real world stuff.
[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]
Becomes:
[3][9][5][1]
[4][0][6][2]
[5][1][7][3]
[6][2][8][4]
Update: Nick's answer is the most straightforward, but is there a way to do it better than n^2? What if the matrix was 10000x10000?
Here is one that does the rotation in place instead of using a completely new array to hold the result. I've left off initialization of the array and printing it out. This only works for square arrays but they can be of any size. Memory overhead is equal to the size of one element of the array so you can do the rotation of as large an array as you want.
A couple of people have already put up examples which involve making a new array.
A few other things to consider:
(a) Instead of actually moving the data, simply traverse the "rotated" array differently.
(b) Doing the rotation in-place can be a little trickier. You'll need a bit of scratch place (probably roughly equal to one row or column in size). There's an ancient ACM paper about doing in-place transposes (http://doi.acm.org/10.1145/355719.355729), but their example code is nasty goto-laden FORTRAN.
Addendum:
http://doi.acm.org/10.1145/355611.355612 is another, supposedly superior, in-place transpose algorithm.
From a linear point of view, consider the matrices:
Now take A transpose
And consider the action of A' on B, or B on A'.
Respectively:
This is expandable for any n x n matrix. And applying this concept quickly in code:
This a better version of it in Java: I've made it for a matrix with a different width and height
This code is based on Nick Berardi's post.
I’d like to add a little more detail. In this answer, key concepts are repeated, the pace is slow and intentionally repetitive. The solution provided here is not the most syntactically compact, it is however, intended for those who wish to learn what matrix rotation is and the resulting implementation.
Firstly, what is a matrix? For the purposes of this answer, a matrix is just a grid where the width and height are the same. Note, the width and height of a matrix can be different, but for simplicity, this tutorial considers only matrices with equal width and height (square matrices). And yes, matrices is the plural of matrix.
Example matrices are: 2×2, 3×3 or 5×5. Or, more generally, N×N. A 2×2 matrix will have 4 squares because 2×2=4. A 5×5 matrix will have 25 squares because 5×5=25. Each square is called an element or entry. We’ll represent each element with a period (
.
) in the diagrams below:2×2 matrix
3×3 matrix
4×4 matrix
So, what does it mean to rotate a matrix? Let’s take a 2×2 matrix and put some numbers in each element so the rotation can be observed:
Rotating this by 90 degrees gives us:
We literally turned the whole matrix once to the right just like turning the steering wheel of a car. It may help to think of “tipping” the matrix onto its right side. We want to write a function, in Python, that takes a matrix and rotates in once to the right. The function signature will be:
The matrix will be defined using a two-dimensional array:
Therefore the first index position accesses the row. The second index position accesses the column:
We’ll define a utility function to print a matrix.
One method of rotating a matrix is to do it a layer at a time. But what is a layer? Think of an onion. Just like the layers of an onion, as each layer is removed, we move towards the center. Other analogies is a Matryoshka doll or a game of pass-the-parcel.
The width and height of a matrix dictate the number of layers in that matrix. Let’s use different symbols for each layer:
A 2×2 matrix has 1 layer
A 3×3 matrix has 2 layers
A 4×4 matrix has 2 layers
A 5×5 matrix has 3 layers
A 6×6 matrix has 3 layers
A 7×7 matrix has 4 layers
You may notice that incrementing the width and height of a matrix by one, does not always increase the number of layers. Taking the above matrices and tabulating the layers and dimensions, we see the number of layers increases once for every two increments of width and height:
However, not all layers need rotating. A 1×1 matrix is the same before and after rotation. The central 1×1 layer is always the same before and after rotation no matter how large the overall matrix:
Given N×N matrix, how can we programmatically determine the number of layers we need to rotate? If we divide the width or height by two and ignore the remainder we get the following results.
Notice how
N/2
matches the number of layers that need to be rotated? Sometimes the number of rotatable layers is one less the total number of layers in the matrix. This occurs when the innermost layer is formed of only one element (i.e. a 1×1 matrix) and therefore need not be rotated. It simply gets ignored.We will undoubtedly need this information in our function to rotate a matrix, so let’s add it now:
Now we know what layers are and how to determine the number of layers that actually need rotating, how do we isolate a single layer so we can rotate it? Firstly, we inspect a matrix from the outermost layer, inwards, to the innermost layer. A 5×5 matrix has three layers in total and two layers that need rotating:
Let’s look at columns first. The position of the columns defining the outermost layer, assuming we count from 0, are 0 and 4:
0 and 4 are also the positions of the rows for the outermost layer.
This will always be the case since the width and height are the same. Therefore we can define the column and row positions of a layer with just two values (rather than four).
Moving inwards to the second layer, the position of the columns are 1 and 3. And, yes, you guessed it, it’s the same for rows. It’s important to understand we had to both increment and decrement the row and column positions when moving inwards to the next layer.
So, to inspect each layer, we want a loop with both increasing and decreasing counters that represent moving inwards, starting from the outermost layer. We’ll call this our ‘layer loop’.
The code above loops through the (row and column) positions of any layers that need rotating.
We now have a loop providing the positions of the rows and columns of each layer. The variables
first
andlast
identify the index position of the first and last rows and columns. Referring back to our row and column tables:So we can navigate through the layers of a matrix. Now we need a way of navigating within a layer so we can move elements around that layer. Note, elements never ‘jump’ from one layer to another, but they do move within their respective layers.
Rotating each element in a layer rotates the entire layer. Rotating all layers in a matrix rotates the entire matrix. This sentence is very important, so please try your best to understand it before moving on.
Now, we need a way of actually moving elements, i.e. rotate each element, and subsequently the layer, and ultimately the matrix. For simplicity, we’ll revert to a 3x3 matrix — that has one rotatable layer.
Our layer loop provides the indexes of the first and last columns, as well as first and last rows:
Because our matrices are always square, we need just two variables,
first
andlast
, since index positions are the same for rows and columns.The variables first and last can easily be used to reference the four corners of a matrix. This is because the corners themselves can be defined using various permutations of
first
andlast
(with no subtraction, addition or offset of those variables):For this reason, we start our rotation at the outer four corners — we’ll rotate those first. Let’s highlight them with
*
.We want to swap each
*
with the*
to the right of it. So let’s go ahead a print out our corners defined using only various permutations offirst
andlast
:Output should be:
Now we could quite easily swap each of the corners from within our layer loop:
Matrix before rotating corners:
Matrix after rotating corners:
Great! We have successfully rotated each corner of the matrix. But, we haven’t rotated the elements in the middle of each layer. Clearly we need a way of iterating within a layer.
The problem is, the only loop in our function so far (our layer loop), moves to the next layer on each iteration. Since our matrix has only one rotatable layer, the layer loop exits after rotating only the corners. Let’s look at what happens with a larger, 5×5 matrix (where two layers need rotating). The function code has been omitted, but it remains the same as above:
The output is:
It shouldn’t be a surprise that the corners of the outermost layer have been rotated, but, you may also notice the corners of the next layer (inwards) have also been rotated. This makes sense. We’ve written code to navigate through layers and also to rotate the corners of each layer. This feels like progress, but unfortunately we must take a step back. It’s just no good moving onto the next layer until the previous (outer) layer has been fully rotated. That is, until each element in the layer has been rotated. Rotating only the corners won’t do!
Take a deep breath. We need another loop. A nested loop no less. The new, nested loop, will use the
first
andlast
variables, plus an offset to navigate within a layer. We’ll call this new loop our ‘element loop’. The element loop will visit each element along the top row, each element down the right side, each element along the bottom row and each element up the left side.This sounds complex, but it’s made easy because the number of times we increment and decrement to achieve the above remains the same along all four sides of the matrix. For example:
This means we can use a single variable in combination with the
first
andlast
variables to move within a layer. It may help to note that moving across the top row and down the right side both require incrementing. While moving backwards along the bottom and up the left side both require decrementing.Now we simply need to assign the top to the right side, right side to the bottom, bottom to the left side, and left side to the top. Putting this all together we get:
Given the matrix:
Our
rotate
function results in:C code for matrix rotation 90 degree clockwise IN PLACE for any M*N matrix