How do you rotate a two dimensional array?
Asked Answered
O

64

367

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?

Odine answered 3/9, 2008 at 20:34 Comment(13)
How could you possibly get away with less than n^2? All elements must be read and set, and there are n^2 elementsSubassembly
See also https://mcmap.net/q/15088/-how-to-efficiently-rotate-bitmaps-in-codeScarlett
The point of asking this question (in Raymond's story) was just to make sure the candidate had a certain set of baseline abilities. The n^2 solution is just fine.Tybi
What is your n? You don't say if the 2D array is square (it's not in the general case! e.g a vector is a matrix with one dimension of 1), yet you seem to imply that n is the width and height, and have therefore n² elements. It would make more sense to have n be the number of elements, with n=w×h.Notify
Agree w/ niXar. Just because N happens to strongly correlate to the square of some other value does not make the solution N^2.Constriction
I don't have time to write it up, but the preferred way to perform rotations is to use quaternions.Chink
It would be more challenging if its dimension is NxM instead of NxN.Humphries
Note that for large arrays, cache misses can be problematic, so you will want to use tiling as suggested in the answer to https://mcmap.net/q/15088/-how-to-efficiently-rotate-bitmaps-in-code. Doing so you will end up with a quadruply nested loop.Evie
Here is a fast way of doing it: store the row and column indices (say i and j). Transpose takes constant time (just swap the indices :). You can do the same with rotations (play with indices).Colonic
In case n^2 is not feasible. You can create an interface which access each element. Then given (i, j), apply rotation to (i, j) access the rotated element and return. Might not be the best soln but works.Mathura
I think you can still do it less than N^2. However, a more complicated data structure is required. Maybe some type of doubly link list?Deutoplasm
@Subassembly could it be compressed?Gutter
I did it with a single loop: https://mcmap.net/q/92350/-how-do-you-rotate-a-two-dimensional-arrayLorola
U
166

Here it is in C#

int[,] array = new int[4,4] {
    { 1,2,3,4 },
    { 5,6,7,8 },
    { 9,0,1,2 },
    { 3,4,5,6 }
};

int[,] rotated = RotateMatrix(array, 4);

static int[,] RotateMatrix(int[,] matrix, int n) {
    int[,] ret = new int[n, n];

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            ret[i, j] = matrix[n - j - 1, i];
        }
    }

    return ret;
}
Ute answered 3/9, 2008 at 20:34 Comment(9)
Sure, but what about a solution using O(1) memory?Tree
Your solution has O(n^2) space complexity. Need to do betterSpecular
How about for N X M matrix ?Saccule
The complexity is linear in the number of elements in the array. If N is the number of elements the complexity is O(N). If N is the length of side, then yes, the complexity is O(N^2), but that is still optimal. You have to read every element at least once. Printing the matrix is the same complexitiyLuvenialuwana
Added an answer for N x M matrix here: https://mcmap.net/q/92350/-how-do-you-rotate-a-two-dimensional-arrayEndblown
@KshitijJain how it is O(n^2) space complexity? He is duplicating array, so isn't it O(n) space?Meggs
For a -90 degrees rotation: ret[i][j] = matrix[j][n - i - 1]Germainegerman
Correct me if I'm wrong, but couldn't parallelism (provided the system has a reasonable number of cores) decrease the complexity even if only slightly?Hamblin
See my answer with a single loop: https://mcmap.net/q/92350/-how-do-you-rotate-a-two-dimensional-arrayLorola
A
484

O(n^2) time and O(1) space algorithm ( without any workarounds and hanky-panky stuff! )

Rotate by +90:

  1. Transpose
  2. Reverse each row

Rotate by -90:

Method 1 :

  1. Transpose
  2. Reverse each column

Method 2 :

  1. Reverse each row
  2. Transpose

Rotate by +180:

Method 1: Rotate by +90 twice

Method 2: Reverse each row and then reverse each column

Rotate by -180:

Method 1: Rotate by -90 twice

Method 2: Reverse each column and then reverse each row

Method 3: Rotate by +180 as they are same

Ashlynashman answered 3/9, 2008 at 20:34 Comment(12)
This was very helpful for me; I was able to write an algorithm once I knew the "[pseudo-]code version" of this operation. Thanks!Ousel
One of my favorite SO answers of all time. Very instructive!Zabaglione
Here's a JavaScript implementation JSFiddle if anyone is interested.Megen
Rotate by -90: (1) Reverse each row; (2) Transpose. Haskell: rotateCW = map reverse . transpose and rotateCCW = transpose . map reverseJeneejenei
To rotate by -90, reversing each row and then transposing will be faster vs. transposing and then reversing each column. Cache coherency is a big dealBonbon
The space would not be O(1) for simple solution "In place matrix transpose" is not that straight forward, For simple solution you have to use a temporary matrix to store transposed matrix. Nevertheless, Nice solution!Skin
Beautiful. It should be noted that O(1) space is not possible if the dimensions are different, as no matter what another array must be created.Pinkiepinkish
What's the difference between rotating 180 and -180?Hourigan
@ElgsQianChen There isn't. 90, 180, 270 corresponds to -270, -180, -90 in the other direction, respectively. Therefore, rotating 90 is the same as rotating -270, and so forth. In effect, only three unique rotations are required for all cases (if 0, the original matrix can simply be returned).Hamblin
Brilliant solution. This has somewhat similarity to 1D array rotation -- which IMHO is its brilliance. There are other solutions on the Internet and this one is the best.Pedometer
Am I the only who is not able to prove correctness of this algorithm? :(Incite
"Method 2: Reverse each row and then reverse each column (Transpose)" I'm not sure why there is a "Transpose" in parentheses here. Reversing each row, then reversing each column is not what the transpose operation does. The transpose operation interchanges rows and columns.Strum
S
261

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:

0 1
2 3

Rotating this by 90 degrees gives us:

2 0
3 1

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 it once to the right. The function signature will be:

def rotate(matrix):
    # Algorithm goes here.

The matrix will be defined using a two-dimensional array:

matrix = [
    [0,1],
    [2,3]
]

Therefore the first index position accesses the row. The second index position accesses the column:

matrix[row][column]

We’ll define a utility function to print a matrix.

def print_matrix(matrix):
    for row in matrix:
        print row

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

. . .
. x .
. . .

A 4×4 matrix has 2 layers

. . . .
. x x .
. x x .
. . . .

A 5×5 matrix has 3 layers

. . . . .
. x x x .
. x O x .
. x x x .
. . . . .

A 6×6 matrix has 3 layers

. . . . . .
. x x x x .
. x O O x .
. x O O x .
. x x x x .
. . . . . .

A 7×7 matrix has 4 layers

. . . . . . .
. x x x x x .
. x O O O x .
. x O - O x .
. x O O O x .
. x x x x x .
. . . . . . .

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:

+-----+--------+
| N×N | Layers |
+-----+--------+
| 1×1 |      1 |
| 2×2 |      1 |
| 3×3 |      2 |
| 4×4 |      2 |
| 5×5 |      3 |
| 6×6 |      3 |
| 7×7 |      4 |
+-----+--------+

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:

+-----+--------+------------------+
| N×N | Layers | Rotatable Layers |
+-----+--------+------------------+
| 1×1 |      1 |                0 |
| 2×2 |      1 |                1 |
| 3×3 |      2 |                1 |
| 4×4 |      2 |                2 |
| 5×5 |      3 |                2 |
| 6×6 |      3 |                3 |
| 7×7 |      4 |                3 |
+-----+--------+------------------+

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.

+-----+--------+------------------+---------+
| N×N | Layers | Rotatable Layers |   N/2   |
+-----+--------+------------------+---------+
| 1×1 |      1 |                0 | 1/2 = 0 |
| 2×2 |      1 |                1 | 2/2 = 1 |
| 3×3 |      2 |                1 | 3/2 = 1 |
| 4×4 |      2 |                2 | 4/2 = 2 |
| 5×5 |      3 |                2 | 5/2 = 2 |
| 6×6 |      3 |                3 | 6/2 = 3 |
| 7×7 |      4 |                3 | 7/2 = 3 |
+-----+--------+------------------+---------+

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:

def rotate(matrix):
    size = len(matrix)
    # Rotatable layers only.
    layer_count = size / 2

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:

. . . . .
. x x x .
. x O x .
. x x x .
. . . . .

Let’s look at columns first. The position of the columns defining the outermost layer, assuming we count from 0, are 0 and 4:

+--------+-----------+
| Column | 0 1 2 3 4 |
+--------+-----------+
|        | . . . . . |
|        | . x x x . |
|        | . x O x . |
|        | . x x x . |
|        | . . . . . |
+--------+-----------+

0 and 4 are also the positions of the rows for the outermost layer.

+-----+-----------+
| Row |           |
+-----+-----------+
|   0 | . . . . . |
|   1 | . x x x . |
|   2 | . x O x . |
|   3 | . x x x . |
|   4 | . . . . . |
+-----+-----------+

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.

+-----------+---------+---------+---------+
|   Layer   |  Rows   | Columns | Rotate? |
+-----------+---------+---------+---------+
| Outermost | 0 and 4 | 0 and 4 | Yes     |
| Inner     | 1 and 3 | 1 and 3 | Yes     |
| Innermost | 2       | 2       | No      |
+-----------+---------+---------+---------+

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’.

def rotate(matrix):
    size = len(matrix)
    layer_count = size / 2

    for layer in range(0, layer_count):
        first = layer
        last = size - first - 1
        print 'Layer %d: first: %d, last: %d' % (layer, first, last)

# 5x5 matrix
matrix = [
    [ 0, 1, 2, 3, 4],
    [ 5, 6, 6, 8, 9],
    [10,11,12,13,14],
    [15,16,17,18,19],
    [20,21,22,23,24]
]

rotate(matrix)

The code above loops through the (row and column) positions of any layers that need rotating.

Layer 0: first: 0, last: 4
Layer 1: first: 1, last: 3

We now have a loop providing the positions of the rows and columns of each layer. The variables first and last identify the index position of the first and last rows and columns. Referring back to our row and column tables:

+--------+-----------+
| Column | 0 1 2 3 4 |
+--------+-----------+
|        | . . . . . |
|        | . x x x . |
|        | . x O x . |
|        | . x x x . |
|        | . . . . . |
+--------+-----------+

+-----+-----------+
| Row |           |
+-----+-----------+
|   0 | . . . . . |
|   1 | . x x x . |
|   2 | . x O x . |
|   3 | . x x x . |
|   4 | . . . . . |
+-----+-----------+

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.

0 1 2
3 4 5
6 7 8

Our layer loop provides the indexes of the first and last columns, as well as first and last rows:

+-----+-------+
| Col | 0 1 2 |
+-----+-------+
|     | 0 1 2 |
|     | 3 4 5 |
|     | 6 7 8 |
+-----+-------+

+-----+-------+
| Row |       |
+-----+-------+
|   0 | 0 1 2 |
|   1 | 3 4 5 |
|   2 | 6 7 8 |
+-----+-------+

Because our matrices are always square, we need just two variables, first and last, since index positions are the same for rows and columns.

def rotate(matrix):
    size = len(matrix)
    layer_count = size / 2

    # Our layer loop i=0, i=1, i=2
    for layer in range(0, layer_count):

        first = layer
        last = size - first - 1
        
        # We want to move within a layer here.

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 and last (with no subtraction, addition or offset of those variables):

+---------------+-------------------+-------------+
| Corner        | Position          | 3x3 Values  |
+---------------+-------------------+-------------+
| top left      | (first, first)    | (0,0)       |
| top right     | (first, last)     | (0,2)       |
| bottom right  | (last, last)      | (2,2)       |
| bottom left   | (last, first)     | (2,0)       |
+---------------+-------------------+-------------+

For this reason, we start our rotation at the outer four corners — we’ll rotate those first. Let’s highlight them with *.

* 1 *
3 4 5
* 7 *

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 of first and last:

def rotate(matrix):
    size = len(matrix)
    layer_count = size / 2
    for layer in range(0, layer_count):

        first = layer
        last = size - first - 1

        top_left = (first, first)
        top_right = (first, last)
        bottom_right = (last, last)
        bottom_left = (last, first)

        print 'top_left: %s' % (top_left)
        print 'top_right: %s' % (top_right)
        print 'bottom_right: %s' % (bottom_right)
        print 'bottom_left: %s' % (bottom_left)

matrix = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
]

rotate(matrix)

Output should be:

top_left: (0, 0)
top_right: (0, 2)
bottom_right: (2, 2)
bottom_left: (2, 0)

Now we could quite easily swap each of the corners from within our layer loop:

def rotate(matrix):
    size = len(matrix)
    layer_count = size / 2
    for layer in range(0, layer_count):
        
        first = layer
        last = size - first - 1

        top_left = matrix[first][first]
        top_right = matrix[first][last]
        bottom_right = matrix[last][last]
        bottom_left = matrix[last][first]

        # bottom_left -> top_left
        matrix[first][first] = bottom_left
        # top_left -> top_right
        matrix[first][last] = top_left
        # top_right -> bottom_right
        matrix[last][last] = top_right
        # bottom_right -> bottom_left
        matrix[last][first] = bottom_right


print_matrix(matrix)
print '---------'
rotate(matrix)
print_matrix(matrix)

Matrix before rotating corners:

[0, 1, 2]
[3, 4, 5]
[6, 7, 8]

Matrix after rotating corners:

[6, 1, 0]
[3, 4, 5]
[8, 7, 2]

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:

matrix = [
[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]
]
print_matrix(matrix)
print '--------------------'
rotate(matrix)
print_matrix(matrix)

The output is:

[20,  1,  2,  3,  0]
[ 5, 16,  7,  6,  9]
[10, 11, 12, 13, 14]
[15, 18, 17,  8, 19]
[24, 21, 22, 23,  4]

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 and last 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.

  • Moving forwards along the top row requires the column index to be incremented.
  • Moving down the right side requires the row index to be incremented.
  • Moving backwards along the bottom requires the column index to be decremented.
  • Moving up the left side requires the row index to be decremented.

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:

  • Move 1 element across the top row.
  • Move 1 element down the right side.
  • Move 1 element backwards along the bottom row.
  • Move 1 element up the left side.

This means we can use a single variable in combination with the first and last 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.

def rotate(matrix):
    size = len(matrix)
    layer_count = size / 2
    
    # Move through layers (i.e. layer loop).
    for layer in range(0, layer_count):
        
            first = layer
            last = size - first - 1

            # Move within a single layer (i.e. element loop).
            for element in range(first, last):
            
                offset = element - first

                # 'element' increments column (across right)
                top = (first, element)
                # 'element' increments row (move down)
                right_side = (element, last)
                # 'last-offset' decrements column (across left)
                bottom = (last, last-offset)
                # 'last-offset' decrements row (move up)
                left_side = (last-offset, first)

                print 'top: %s' % (top)
                print 'right_side: %s' % (right_side)
                print 'bottom: %s' % (bottom)
                print 'left_side: %s' % (left_side)

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:

def rotate(matrix):
    size = len(matrix)
    layer_count = size / 2

    for layer in range(0, layer_count):
        first = layer
        last = size - first - 1

        for element in range(first, last):
            offset = element - first

            top = matrix[first][element]
            right_side = matrix[element][last]
            bottom = matrix[last][last-offset]
            left_side = matrix[last-offset][first]

            matrix[first][element] = left_side
            matrix[element][last] = top
            matrix[last][last-offset] = right_side
            matrix[last-offset][first] = bottom

Given the matrix:

0,  1,  2  
3,  4,  5  
6,  7,  8 

Our rotate function results in:

6,  3,  0  
7,  4,  1  
8,  5,  2  
Shikari answered 3/9, 2008 at 20:34 Comment(9)
@AbhijitSarkar - Thanks for up-voting and I hope it at least helped in some small way. Of course, you're right, my answer is wordy. This was however intentionally in contrast to the vast majority of answers. As I said at the very start of my answer: "In this answer, key concepts are repeated, the pace is slow and intentionally repetitive." If you have edits which keep the clarity and necessary repetitiveness but reduce the word count, I'm very open to suggestions. Or just edit :)Shikari
@jack Really good explanation. However, I could not unddrstand, how did you come up with offset = element - first and last = size - first - 1? Having hard time understanding this? Also, is last-offset same as offset?Soapbox
TL;DR: list(zip(*reversed(your_list_of_lists)))Yhvh
Another upvote. Probably the best Stackoverflow post I have seen. More a beautiful tutorial than an answer to a question. Thanks for your effort. Small error: top_element = (first, element) should be: top = (first, element) in the second last block of pseudo-code.Infusorian
@Infusorian Thank you, and thanks for flagging the error. I've updated the question :)Shikari
@Shikari one of the best code explanations I have ever come across. Should be in the ELI5 sub-reddit. Very organic and intuitive.Similarity
@Similarity thanks. I'm happy to write more guides or for this to be shared in ELI5Shikari
@Shikari I have to login to thank you for the great answer. it was very helpful and very detailLindyline
I like this answer more, as it gives a logical /natural approach to understanding a matrix rotation, without linear algebra. At first it took me a bit to understand the onion reference. But It finally clicked when I visualized looking down at the matrix from above and starting from the outer square "lift" up the outer square and you're left with the inner squares. Repeat till final layer.Accidental
U
166

Here it is in C#

int[,] array = new int[4,4] {
    { 1,2,3,4 },
    { 5,6,7,8 },
    { 9,0,1,2 },
    { 3,4,5,6 }
};

int[,] rotated = RotateMatrix(array, 4);

static int[,] RotateMatrix(int[,] matrix, int n) {
    int[,] ret = new int[n, n];

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            ret[i, j] = matrix[n - j - 1, i];
        }
    }

    return ret;
}
Ute answered 3/9, 2008 at 20:34 Comment(9)
Sure, but what about a solution using O(1) memory?Tree
Your solution has O(n^2) space complexity. Need to do betterSpecular
How about for N X M matrix ?Saccule
The complexity is linear in the number of elements in the array. If N is the number of elements the complexity is O(N). If N is the length of side, then yes, the complexity is O(N^2), but that is still optimal. You have to read every element at least once. Printing the matrix is the same complexitiyLuvenialuwana
Added an answer for N x M matrix here: https://mcmap.net/q/92350/-how-do-you-rotate-a-two-dimensional-arrayEndblown
@KshitijJain how it is O(n^2) space complexity? He is duplicating array, so isn't it O(n) space?Meggs
For a -90 degrees rotation: ret[i][j] = matrix[j][n - i - 1]Germainegerman
Correct me if I'm wrong, but couldn't parallelism (provided the system has a reasonable number of cores) decrease the complexity even if only slightly?Hamblin
See my answer with a single loop: https://mcmap.net/q/92350/-how-do-you-rotate-a-two-dimensional-arrayLorola
B
136

Python:

rotated = list(zip(*original[::-1]))

and counterclockwise:

rotated_ccw = list(zip(*original))[::-1]

How this works:

zip(*original) will swap axes of 2d arrays by stacking corresponding items from lists into new lists. (The * operator tells the function to distribute the contained lists into arguments)

>>> list(zip(*[[1,2,3],[4,5,6],[7,8,9]]))
[[1,4,7],[2,5,8],[3,6,9]]

The [::-1] statement reverses array elements (please see Extended Slices or this question):

>>> [[1,2,3],[4,5,6],[7,8,9]][::-1]
[[7,8,9],[4,5,6],[1,2,3]]

Finally, combining the two will result in the rotation transformation.

The change in placement of [::-1] will reverse lists in different levels of the matrix.

Beale answered 3/9, 2008 at 20:34 Comment(2)
I believe this code originates from Peter Norvig: norvig.com/python-iaq.htmlNinette
You can use zip(*reversed(original)) instead of zip(*original[::-1]) to avoid creating an extra copy of the original list.Yhvh
C
81

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.

int a[4][4];
int n = 4;
int tmp;
for (int i = 0; i < n / 2; i++)
{
    for (int j = i; j < n - i - 1; j++)
    {
        tmp             = a[i][j];
        a[i][j]         = a[j][n-i-1];
        a[j][n-i-1]     = a[n-i-1][n-j-1];
        a[n-i-1][n-j-1] = a[n-j-1][i];
        a[n-j-1][i]     = tmp;
    }
}
Cyrenaic answered 3/9, 2008 at 20:34 Comment(11)
I can see at least one bug. If you're going to post code, test it or at least say you haven't done so.Drumlin
Where? Point it out and I'll fix it. I did test it and it worked fine on both odd and even sized arrays.Cyrenaic
Just from looking: The second loop starts tests j < -i-1. It looks like j is always >= 0 and -i-1 is always negative, so the test never passes.Shuttle
You're right. That's strange. I believe there is supposed to be an n in there that I left out when I posted it. Fixed it in the listing.Cyrenaic
its a beautiful solution. Mind can perform such feats if set to purpose. from O(n2) to O(1)Perugia
It's not O(1); it's still O(n^2)Ousel
Its O(n^2) with memory O(1).Keavy
I really link the way you divide the array :)Burkle
The key to applying this is "in place";Crowd
bear in mind that this is counter-clockwise rotation only --perhaps clockwise rotation is left as an exercise for the student? ;)Alathia
Similar solution is mentioned at below link geeksforgeeks.org/inplace-rotate-square-matrix-by-90-degreesSwanskin
G
41

There are tons of good code here but I just want to show what's going on geometrically so you can understand the code logic a little better. Here is how I would approach this.

first of all, do not confuse this with transposition which is very easy..

the basica idea is to treat it as layers and we rotate one layer at a time..

say we have a 4x4

1   2   3   4
5   6   7   8
9   10  11  12
13  14  15  16

after we rotate it clockwise by 90 we get

13  9   5   1
14  10  6   2   
15  11  7   3
16  12  8   4

so let's decompose this, first we rotate the 4 corners essentially

1           4


13          16

then we rotate the following diamond which is sort of askew

    2
            8
9       
        15

and then the 2nd skewed diamond

        3
5           
            12
    14

so that takes care of the outer edge so essentially we do that one shell at a time until

finally the middle square (or if it's odd just the final element which does not move)

6   7
10  11

so now let's figure out the indices of each layer, assume we always work with the outermost layer, we are doing

[0,0] -> [0,n-1], [0,n-1] -> [n-1,n-1], [n-1,n-1] -> [n-1,0], and [n-1,0] -> [0,0]
[0,1] -> [1,n-1], [1,n-2] -> [n-1,n-2], [n-1,n-2] -> [n-2,0], and [n-2,0] -> [0,1]
[0,2] -> [2,n-2], [2,n-2] -> [n-1,n-3], [n-1,n-3] -> [n-3,0], and [n-3,0] -> [0,2]

so on and so on until we are halfway through the edge

so in general the pattern is

[0,i] -> [i,n-i], [i,n-i] -> [n-1,n-(i+1)], [n-1,n-(i+1)] -> [n-(i+1),0], and [n-(i+1),0] to [0,i]
Griffy answered 3/9, 2008 at 20:34 Comment(3)
what does it mean "halfway through the edge"? I see a lot of algorithms looping until N/2 and others looping til N, but I can't see where the N/2 is coming from.Marti
I believe its the same solution as given in cracking the coding interview. But I like the step by step explanation. Very nice and thorough.Tyre
@Marti This answer explains it in detail.Usually
M
38

As I said in my previous post, here's some code in C# that implements an O(1) matrix rotation for any size matrix. For brevity and readability there's no error checking or range checking. The code:

static void Main (string [] args)
{
  int [,]
    //  create an arbitrary matrix
    m = {{0, 1}, {2, 3}, {4, 5}};

  Matrix
    //  create wrappers for the data
    m1 = new Matrix (m),
    m2 = new Matrix (m),
    m3 = new Matrix (m);

  //  rotate the matricies in various ways - all are O(1)
  m1.RotateClockwise90 ();
  m2.Rotate180 ();
  m3.RotateAnitclockwise90 ();

  //  output the result of transforms
  System.Diagnostics.Trace.WriteLine (m1.ToString ());
  System.Diagnostics.Trace.WriteLine (m2.ToString ());
  System.Diagnostics.Trace.WriteLine (m3.ToString ());
}

class Matrix
{
  enum Rotation
  {
    None,
    Clockwise90,
    Clockwise180,
    Clockwise270
  }

  public Matrix (int [,] matrix)
  {
    m_matrix = matrix;
    m_rotation = Rotation.None;
  }

  //  the transformation routines
  public void RotateClockwise90 ()
  {
    m_rotation = (Rotation) (((int) m_rotation + 1) & 3);
  }

  public void Rotate180 ()
  {
    m_rotation = (Rotation) (((int) m_rotation + 2) & 3);
  }

  public void RotateAnitclockwise90 ()
  {
    m_rotation = (Rotation) (((int) m_rotation + 3) & 3);
  }

  //  accessor property to make class look like a two dimensional array
  public int this [int row, int column]
  {
    get
    {
      int
        value = 0;

      switch (m_rotation)
      {
      case Rotation.None:
        value = m_matrix [row, column];
        break;

      case Rotation.Clockwise90:
        value = m_matrix [m_matrix.GetUpperBound (0) - column, row];
        break;

      case Rotation.Clockwise180:
        value = m_matrix [m_matrix.GetUpperBound (0) - row, m_matrix.GetUpperBound (1) - column];
        break;

      case Rotation.Clockwise270:
        value = m_matrix [column, m_matrix.GetUpperBound (1) - row];
        break;
      }

      return value;
    }

    set
    {
      switch (m_rotation)
      {
      case Rotation.None:
        m_matrix [row, column] = value;
        break;

      case Rotation.Clockwise90:
        m_matrix [m_matrix.GetUpperBound (0) - column, row] = value;
        break;

      case Rotation.Clockwise180:
        m_matrix [m_matrix.GetUpperBound (0) - row, m_matrix.GetUpperBound (1) - column] = value;
        break;

      case Rotation.Clockwise270:
        m_matrix [column, m_matrix.GetUpperBound (1) - row] = value;
        break;
      }
    }
  }

  //  creates a string with the matrix values
  public override string ToString ()
  {
    int
      num_rows = 0,
      num_columns = 0;

    switch (m_rotation)
    {
    case Rotation.None:
    case Rotation.Clockwise180:
      num_rows = m_matrix.GetUpperBound (0);
      num_columns = m_matrix.GetUpperBound (1);
      break;

    case Rotation.Clockwise90:
    case Rotation.Clockwise270:
      num_rows = m_matrix.GetUpperBound (1);
      num_columns = m_matrix.GetUpperBound (0);
      break;
    }

    StringBuilder
      output = new StringBuilder ();

    output.Append ("{");

    for (int row = 0 ; row <= num_rows ; ++row)
    {
      if (row != 0)
      {
        output.Append (", ");
      }

      output.Append ("{");

      for (int column = 0 ; column <= num_columns ; ++column)
      {
        if (column != 0)
        {
          output.Append (", ");
        }

        output.Append (this [row, column].ToString ());
      }

      output.Append ("}");
    }

    output.Append ("}");

    return output.ToString ();
  }

  int [,]
    //  the original matrix
    m_matrix;

  Rotation
    //  the current view of the matrix
    m_rotation;
}

OK, I'll put my hand up, it doesn't actually do any modifications to the original array when rotating. But, in an OO system that doesn't matter as long as the object looks like it's been rotated to the clients of the class. At the moment, the Matrix class uses references to the original array data so changing any value of m1 will also change m2 and m3. A small change to the constructor to create a new array and copy the values to it will sort that out.

Mona answered 3/9, 2008 at 20:34 Comment(6)
Bravo! This is a very nice solution and I don't know why it isn't the accepted answer.Hussein
@martinatime: perhaps because it is 5 times as bigDutiable
@Toad: Well, writing code is always a trade off between competing requirements: speed, size, cost, etc.Mona
true... another problem is the fact that the matrix is in fact not rotated, but is rotated 'just in time'. Which is great for accessing a few elements, but would be horrible if this matrix was used in calculations or image manipulations. So saying O(1) is not really fair.Dutiable
@Dutiable have you benchmarked it to make any statement about this being horrible? This Solution could be optimized by removing m_matrix.GetUpperBound() calls and the switch. After that it boils down to accessing the base array something like this Matrix[width-x,height-y] which is not so far from Matrix[x,y], in my tests it was same speed. Another Advantage is, you can work on even larger calculations or images, since you dont have to store it twice. Its totally parallelizable, no swapping lines/elements, no memory copying. Even caching is 2 For loops away with optimal O(N*N).Lezley
If you are interested in just a few elements of the rotated matrix, this code is fine. It's readable, its understandable and it just retrieves the elements. However when performing the full rotation, this code will be slow. For every element it has the overhead of a method call, 2d array lookups (that has a multiplication), every set/get has a switch in it, who knows what it does for memory caching, etc So I would wager that removing all the fluff and having a really fast loop swapping elements in place would be way quicker than this. Would it be more readable? Probably not.Dutiable
B
24

Whilst rotating the data in place might be necessary (perhaps to update the physically stored representation), it becomes simpler and possibly more performant to add a layer of indirection onto the array access, perhaps an interface:

interface IReadableMatrix
{
    int GetValue(int x, int y);
}

If your Matrix already implements this interface, then it can be rotated via a decorator class like this:

class RotatedMatrix : IReadableMatrix
{
    private readonly IReadableMatrix _baseMatrix;

    public RotatedMatrix(IReadableMatrix baseMatrix)
    {
        _baseMatrix = baseMatrix;
    }

    int GetValue(int x, int y)
    {
        // transpose x and y dimensions
        return _baseMatrix(y, x);
    }
}

Rotating +90/-90/180 degrees, flipping horizontally/vertically and scaling can all be achieved in this fashion as well.

Performance would need to be measured in your specific scenario. However the O(n^2) operation has now been replaced with an O(1) call. It's a virtual method call which is slower than direct array access, so it depends upon how frequently the rotated array is used after rotation. If it's used once, then this approach would definitely win. If it's rotated then used in a long-running system for days, then in-place rotation might perform better. It also depends whether you can accept the up-front cost.

As with all performance issues, measure, measure, measure!

Barvick answered 3/9, 2008 at 20:34 Comment(18)
+1... And if the matrix is really large and you only access a couple elements (sparse use) it's even more effectiveStreet
What's happening under the covers here? Is it just aliasing or is the memory actually changing?Tybi
@jeffamaphone, the memory isn't changing. I guess you could think of it as aliasing, yes.Barvick
Will this work if I call GetValue(3,3). It will always return the original value and no transposition happens?Roster
@Sesh, yes it still works because (A,B) is the same as (B,A) when A==B.Barvick
It seems a little unfair to call this an O(1) time solution. To solve the problem posed by the OP this will still take O(n^2) time. Not only that, it wouldn't solve the problem because it returns the transpose. The example given doesn't have the transpose as the solution.Transubstantiation
@Goose Bumper -- the point is that the transposition isn't required to physically take place. Printing the matrix out takes O(n^2), but so does any exhaustive read operation, so you can't get away from that. The transposition was O(1) and each individual read is also O(1), so I stick by my assertion that this solution has constant time for rotation and subsequent reads. As I mention in the answer, this technique is not always the most appropriate.Barvick
@Paul Betts, care to elaborate? I'm not trying do disagree, but I'm just curious about your reasoning.Spiffy
@Paul Betts, please give more reasoning. I can't see how this isn't O(1). Anyway, who says I wanted to work for you? :)Barvick
Because to get the full contents of the new array, I must write the function: for(i=1 to n) { for(j=1 to n) { rotated.GetValue(i,j); } } You haven't magically made this constant time, you've just made someone else write the loop.Teniafuge
Now, if all you wanted was the first 3 elements of the matrix, this is a fine solution, but the problem is to retrieve a completely transformed matrix (i.e. assuming you need all the matrix elements). Calling this O(1) is the Credit Default Swap method of Algorithm Analysis - you haven't solved the problem, you've just pushed it to someone else :)Teniafuge
@Paul Betts: I get your point, but like I wrote above in the comments, even if you actually have the matrix transposed you still have to write the loop if you want to read the values out. So reading all values from a matrix is always O(N^2) regardless. The difference here is that if you transpose, rotate, scale, scale again, etc, then you still only take the O(N^2) hit once. Like I said, this isn't always the best solution, but in many cases it's appropriate and worthwhile. The OP seemed to be looking for a magic solution, and this is as close as you'll get.Barvick
As you say, if you only need 3 elements then this is faster, but I maintain that it's faster in most cases anyway. What good are the bytes laid out in memory if you don't read them? Whether it be random or sequential access, there's still a cost with reading them. This solution just avoids you having to read them all at the time you transfer them and then again later. You only do the read once. If you're hammering the matrix array for reads, then you might want a permanent version because the cost of dispatching virtual calls might start to outweigh the benefit of this approach.Barvick
Another consideration is whether the source matrix is immutable. This technique only works if the source doesn't change under you. There's another way of thinking about this approach. Rather than returning an array, we return the promise to provide the array when (and if) it's needed. It's similar to IEnumerable. 'Calculation' is lazy.Barvick
I like this answer, but I want to point something out. Printing out the decorated matrix (and doing other sequential reads in general) may be much slower than doing the same to a matrix that's been rotated in memory, and it's not just because of virtual method calls. For a big matrix, you're going to vastly increase the number of cache misses you get by reading "down" rather than "across".Underpay
@drew noakes, @paul betts : however you explain it, paul bett's point is valid. You didn't rotate the matrix but added layers of indirection which will do the transformation 'just in time'. Doing anything substantial with this matrix (matrix calculations or image manipulation) will seriously slow down because of it.Dutiable
@Toad, yep. Like I said in the post and in the comments, it all depends. No one showed this solution here, and it's worth thinking about, even if you don't use it. In some cases, it'll be much better than rotating the array in memory.Barvick
@MikeDaniels: That's not quite the full story, because if you had simply rotated the array in place "the hard way" at the outset, you would have needed to take those same cache hits then. Drew's solution will only be much slower if you perform many operations on elements in row-major order after "rotating" (decorating) it.Cultivate
O
20

This a better version of it in Java: I've made it for a matrix with a different width and height

  • h is here the height of the matrix after rotating
  • w is here the width of the matrix after rotating

 

public int[][] rotateMatrixRight(int[][] matrix)
{
    /* W and H are already swapped */
    int w = matrix.length;
    int h = matrix[0].length;
    int[][] ret = new int[h][w];
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            ret[i][j] = matrix[w - j - 1][i];
        }
    }
    return ret;
}


public int[][] rotateMatrixLeft(int[][] matrix)
{
    /* W and H are already swapped */
    int w = matrix.length;
    int h = matrix[0].length;   
    int[][] ret = new int[h][w];
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            ret[i][j] = matrix[j][h - i - 1];
        }
    }
    return ret;
}

This code is based on Nick Berardi's post.

Obrien answered 3/9, 2008 at 20:34 Comment(1)
Thanks. This was the clearest Java code here. Question - How did you/Nick come up with the [w - j - 1] part? Looking at @Griffy answer i can see how you could derive that through induction/solving examples. Just wondering if thats how it was obtained or is it based on some mathematical principle pertaining to Matrices.Emoryemote
K
18

Ruby-way: .transpose.map &:reverse

Karelia answered 3/9, 2008 at 20:34 Comment(1)
It's even simpler than that: array.reverse.transpose rotates an array clockwise, while array.transpose.reverse rotates it counterclockwise. There's no need for map.Qumran
C
16

There are a lot of answers already, and I found two claiming O(1) time complexity. The real O(1) algorithm is to leave the array storage untouched, and change how you index its elements. The goal here is that it does not consume additional memory, nor does it require additional time to iterate the data.

Rotations of 90, -90 and 180 degrees are simple transformations which can be performed as long as you know how many rows and columns are in your 2D array; To rotate any vector by 90 degrees, swap the axes and negate the Y axis. For -90 degree, swap the axes and negate the X axis. For 180 degrees, negate both axes without swapping.

Further transformations are possible, such as mirroring horizontally and/or vertically by negating the axes independently.

This can be done through e.g. an accessor method. The examples below are JavaScript functions, but the concepts apply equally to all languages.

 // Get an array element in column/row order
 var getArray2d = function(a, x, y) {
   return a[y][x];
 };

 //demo
 var arr = [
   [5, 4, 6],
   [1, 7, 9],
   [-2, 11, 0],
   [8, 21, -3],
   [3, -1, 2]
 ];

 var newarr = [];
 arr[0].forEach(() => newarr.push(new Array(arr.length)));

 for (var i = 0; i < newarr.length; i++) {
   for (var j = 0; j < newarr[0].length; j++) {
     newarr[i][j] = getArray2d(arr, i, j);
   }
 }
 console.log(newarr);

// Get an array element rotated 90 degrees clockwise
function getArray2dCW(a, x, y) {
  var t = x;
  x = y;
  y = a.length - t - 1;
  return a[y][x];
}

//demo
var arr = [
  [5, 4, 6],
  [1, 7, 9],
  [-2, 11, 0],
  [8, 21, -3],
  [3, -1, 2]
];

var newarr = [];
arr[0].forEach(() => newarr.push(new Array(arr.length)));

for (var i = 0; i < newarr[0].length; i++) {
  for (var j = 0; j < newarr.length; j++) {
    newarr[j][i] = getArray2dCW(arr, i, j);
  }
}
console.log(newarr);

// Get an array element rotated 90 degrees counter-clockwise
function getArray2dCCW(a, x, y) {
  var t = x;
  x = a[0].length - y - 1;
  y = t;
  return a[y][x];
}

//demo
var arr = [
  [5, 4, 6],
  [1, 7, 9],
  [-2, 11, 0],
  [8, 21, -3],
  [3, -1, 2]
];

var newarr = [];
arr[0].forEach(() => newarr.push(new Array(arr.length)));

for (var i = 0; i < newarr[0].length; i++) {
  for (var j = 0; j < newarr.length; j++) {
    newarr[j][i] = getArray2dCCW(arr, i, j);
  }
}
console.log(newarr);

// Get an array element rotated 180 degrees
function getArray2d180(a, x, y) {
  x = a[0].length - x - 1;
  y = a.length - y - 1;
  return a[y][x];
}

//demo
var arr = [
  [5, 4, 6],
  [1, 7, 9],
  [-2, 11, 0],
  [8, 21, -3],
  [3, -1, 2]
];

var newarr = [];
arr.forEach(() => newarr.push(new Array(arr[0].length)));

for (var i = 0; i < newarr[0].length; i++) {
  for (var j = 0; j < newarr.length; j++) {
    newarr[j][i] = getArray2d180(arr, i, j);
  }
}
console.log(newarr);

This code assumes an array of nested arrays, where each inner array is a row.

The method allows you to read (or write) elements (even in random order) as if the array has been rotated or transformed. Now just pick the right function to call, probably by reference, and away you go!

The concept can be extended to apply transformations additively (and non-destructively) through the accessor methods. Including arbitrary angle rotations and scaling.

Colpotomy answered 3/9, 2008 at 20:34 Comment(5)
None of these actually rotated from the original array though. The first one, the end result is simply transposed. The second one, you appear to have just shuffled the rows or mirrored across the horizontal center. The third, you only reversed the rows and the fourth is also transposed. None of which were actually "rotated".Buff
There are some bugs in the latter two examples. Trivial to fix. I pointed out explicitly that this solution is not an in-place rotation. It is a transformation function, which makes it suitable for lazy iteration.Colpotomy
Except there's no rotation so you didn't actually answer what the OP asked.Buff
@Buff Another editor added non-working example code to my answer. I can see how you were confused by it. I have fixed the bugs in the iteration loops. The functions as provided do in fact "rotate" the data in the arrays.Colpotomy
Also important detail is that the example code really washes out the original answer that I provided, which was trying to illustrate the power of functional transformations over linear space-time complexity solutions. With a functional transformation you are already iterating or otherwise accessing the array elements, so the transformation is considered "free" in the sense of constant space and time complexity.Colpotomy
R
10

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.

Raddled answered 3/9, 2008 at 20:34 Comment(1)
I agree with this. Have a method that determine the translation between the source data and the "rotated" data.Hussein
S
9

Nick's answer would work for an NxM array too with only a small modification (as opposed to an NxN).

string[,] orig = new string[n, m];
string[,] rot = new string[m, n];

...

for ( int i=0; i < n; i++ )
  for ( int j=0; j < m; j++ )
    rot[j, n - i - 1] = orig[i, j];

One way to think about this is that you have moved the center of the axis (0,0) from the top left corner to the top right corner. You're simply transposing from one to the other.

Sly answered 3/9, 2008 at 20:34 Comment(0)
G
7

A common method to rotate a 2D array clockwise or anticlockwise.

  • clockwise rotate
    • first reverse up to down, then swap the symmetry
      1 2 3     7 8 9     7 4 1
      4 5 6  => 4 5 6  => 8 5 2
      7 8 9     1 2 3     9 6 3
      
void rotate(vector<vector<int> > &matrix) {
    reverse(matrix.begin(), matrix.end());
    for (int i = 0; i < matrix.size(); ++i) {
        for (int j = i + 1; j < matrix[i].size(); ++j)
            swap(matrix[i][j], matrix[j][i]);
    }
}
  • anticlockwise rotate
    • first reverse left to right, then swap the symmetry
      1 2 3     3 2 1     3 6 9
      4 5 6  => 6 5 4  => 2 5 8
      7 8 9     9 8 7     1 4 7
      
void anti_rotate(vector<vector<int> > &matrix) {
    for (auto vi : matrix) reverse(vi.begin(), vi.end());
    for (int i = 0; i < matrix.size(); ++i) {
        for (int j = i + 1; j < matrix[i].size(); ++j)
            swap(matrix[i][j], matrix[j][i]);
    }
}
Gombroon answered 3/9, 2008 at 20:34 Comment(1)
I like this solution because it's pretty intuitive and straight forward, thanksCarr
I
7

Time - O(N), Space - O(1)

public void rotate(int[][] matrix) {
    int n = matrix.length;
    for (int i = 0; i < n / 2; i++) {
        int last = n - 1 - i;
        for (int j = i; j < last; j++) {
            int top = matrix[i][j];
            matrix[i][j] = matrix[last - j][i];
            matrix[last - j][i] = matrix[last][last - j];
            matrix[last][last - j] = matrix[j][last];
            matrix[j][last] = top;
        }
    }
}
Irrespirable answered 3/9, 2008 at 20:34 Comment(5)
This is not O(1). This is O(n).Colpotomy
@JasonOster I believe this is O(1) space, since it consumes no additional space.Desmoid
@Desmoid My mistake. O(1) space complexity, yes. O(n) time complexity.Colpotomy
Space Complexity is O(n) as well. Space Complexity should include the space of input variable size. careercup.com/question?id=14952322Lammers
How could I modify this to work for a counterclockwise rotation?Challah
E
6

Here's my Ruby version (note the values aren't displayed the same, but it still rotates as described).

def rotate(matrix)
  result = []
  4.times { |x|
    result[x] = []
    4.times { |y|
      result[x][y] = matrix[y][3 - x]
    }
  }

  result
end

matrix = []
matrix[0] = [1,2,3,4]
matrix[1] = [5,6,7,8]
matrix[2] = [9,0,1,2]
matrix[3] = [3,4,5,6]

def print_matrix(matrix)
  4.times { |y|
    4.times { |x|
      print "#{matrix[x][y]} "
    }
    puts ""
  }
end

print_matrix(matrix)
puts ""
print_matrix(rotate(matrix))

The output:

1 5 9 3 
2 6 0 4 
3 7 1 5 
4 8 2 6 

4 3 2 1 
8 7 6 5 
2 1 0 9 
6 5 4 3
Eleanoreleanora answered 3/9, 2008 at 20:34 Comment(0)
A
5

here's a in-space rotate method, by java, only for square. for non-square 2d array, you will have to create new array anyway.

private void rotateInSpace(int[][] arr) {
    int z = arr.length;
    for (int i = 0; i < z / 2; i++) {
        for (int j = 0; j < (z / 2 + z % 2); j++) {
            int x = i, y = j;
            int temp = arr[x][y];
            for (int k = 0; k < 4; k++) {
                int temptemp = arr[y][z - x - 1];
                arr[y][z - x - 1] = temp;
                temp = temptemp;

                int tempX = y;
                y = z - x - 1;
                x = tempX;
            }
        }
    }
}

code to rotate any size 2d array by creating new array:

private int[][] rotate(int[][] arr) {
    int width = arr[0].length;
    int depth = arr.length;
    int[][] re = new int[width][depth];
    for (int i = 0; i < depth; i++) {
        for (int j = 0; j < width; j++) {
            re[j][depth - i - 1] = arr[i][j];
        }
    }
    return re;
}
Apiarian answered 3/9, 2008 at 20:34 Comment(0)
H
4

You can do this in 3 easy steps:

1)Suppose we have a matrix

   1 2 3
   4 5 6
   7 8 9

2)Take the transpose of the matrix

   1 4 7
   2 5 8
   3 6 9

3)Interchange rows to get rotated matrix

   3 6 9
   2 5 8
   1 4 7

Java source code for this:

public class MyClass {

    public static void main(String args[]) {
        Demo obj = new Demo();
        /*initial matrix to rotate*/
        int[][] matrix = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
        int[][] transpose = new int[3][3]; // matrix to store transpose

        obj.display(matrix);              // initial matrix

        obj.rotate(matrix, transpose);    // call rotate method
        System.out.println();
        obj.display(transpose);           // display the rotated matix
    }
}

class Demo {   
    public void rotate(int[][] mat, int[][] tran) {

        /* First take the transpose of the matrix */
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat.length; j++) {
                tran[i][j] = mat[j][i]; 
            }
        }

        /*
         * Interchange the rows of the transpose matrix to get rotated
         * matrix
         */
        for (int i = 0, j = tran.length - 1; i != j; i++, j--) {
            for (int k = 0; k < tran.length; k++) {
                swap(i, k, j, k, tran);
            }
        }
    }

    public void swap(int a, int b, int c, int d, int[][] arr) {
        int temp = arr[a][b];
        arr[a][b] = arr[c][d];
        arr[c][d] = temp;    
    }

    /* Method to display the matrix */
    public void display(int[][] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}

Output:

1 2 3 
4 5 6 
7 8 9 

3 6 9 
2 5 8 
1 4 7 
Heti answered 3/9, 2008 at 20:34 Comment(0)
L
3

In python:

import numpy as np

a = np.array(
    [
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 0, 1, 2],
        [3, 4, 5, 6]
    ]
)

print(a)
print(b[::-1, :].T)
Lorrinelorry answered 3/9, 2008 at 20:34 Comment(0)
C
3

Implementation of dimple's +90 pseudocode (e.g. transpose then reverse each row) in JavaScript:

function rotate90(a){
  // transpose from http://www.codesuck.com/2012/02/transpose-javascript-array-in-one-line.html
  a = Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
  // row reverse
  for (i in a){
    a[i] = a[i].reverse();
  }
  return a;
}
Conglobate answered 3/9, 2008 at 20:34 Comment(0)
D
2

Great answers but for those who are looking for a DRY JavaScript code for this - both +90 Degrees and -90 Degrees:

          // Input: 1 2 3
          //        4 5 6
          //        7 8 9

          // Transpose: 
          //       1 4 7
          //       2 5 8
          //       3 6 9

          // Output: 
          // +90 Degree:
          //       7 4 1
          //       8 5 2
          //       9 6 3

          // -90 Degree:
          //      3 6 9
          //      2 5 8
          //      1 4 7

          // Rotate +90
         function rotate90(matrix) {

           matrix = transpose(matrix);
           matrix.map(function(array) {
             array.reverse();
           });

           return matrix;
         }

          // Rotate -90
         function counterRotate90(matrix) {
           var result = createEmptyMatrix(matrix.length);
           matrix = transpose(matrix);
           var counter = 0;

           for (var i = matrix.length - 1; i >= 0; i--) {
             result[counter] = matrix[i];
             counter++;
           }

           return result;
         }

          // Create empty matrix
         function createEmptyMatrix(len) {
           var result = new Array();
           for (var i = 0; i < len; i++) {
             result.push([]);
           }
           return result;
         }

          // Transpose the matrix
         function transpose(matrix) {
           // make empty array
           var len = matrix.length;
           var result = createEmptyMatrix(len);

           for (var i = 0; i < matrix.length; i++) {
             for (var j = 0; j < matrix[i].length; j++) {
               var temp = matrix[i][j];
               result[j][i] = temp;
             }
           }
           return result;
         }



          // Test Cases
         var array1 = [
           [1, 2],
           [3, 4]
         ];
         var array2 = [
           [1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]
         ];
         var array3 = [
           [1, 2, 3, 4],
           [5, 6, 7, 8],
           [9, 10, 11, 12],
           [13, 14, 15, 16]
         ];

          // +90 degress Rotation Tests

         var test1 = rotate90(array1);
         var test2 = rotate90(array2);
         var test3 = rotate90(array3);
         console.log(test1);
         console.log(test2);
         console.log(test3);

          // -90 degress Rotation Tests
         var test1 = counterRotate90(array1);
         var test2 = counterRotate90(array2);
         var test3 = counterRotate90(array3);
         console.log(test1);
         console.log(test2);
         console.log(test3);
Disqualification answered 3/9, 2008 at 20:34 Comment(0)
F
2

C# code to rotate [n,m] 2D arrays 90 deg right

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MatrixProject
{
    // mattrix class

    class Matrix{
        private int rows;
        private int cols;
        private int[,] matrix;

        public Matrix(int n){
            this.rows = n;
            this.cols = n;
            this.matrix = new int[this.rows,this.cols];

        }

        public Matrix(int n,int m){
            this.rows = n;
            this.cols = m;

            this.matrix = new int[this.rows,this.cols];
        }

        public void Show()
        {
            for (var i = 0; i < this.rows; i++)
            {
                for (var j = 0; j < this.cols; j++) {
                    Console.Write("{0,3}", this.matrix[i, j]);
                }
                Console.WriteLine();
            }                
        }

        public void ReadElements()
        {
           for (var i = 0; i < this.rows; i++)
                for (var j = 0; j < this.cols; j++)
                {
                    Console.Write("element[{0},{1}]=",i,j);
                    this.matrix[i, j] = Convert.ToInt32(Console.ReadLine());
                }            
        }


        // rotate [n,m] 2D array by 90 deg right
        public void Rotate90DegRight()
        {

            // create a mirror of current matrix
            int[,] mirror = this.matrix;

            // create a new matrix
            this.matrix = new int[this.cols, this.rows];

            for (int i = 0; i < this.rows; i++)
            {
                for (int j = 0; j < this.cols; j++)
                {
                    this.matrix[j, this.rows - i - 1] = mirror[i, j];
                }
            }

            // replace cols count with rows count
            int tmp = this.rows;
            this.rows = this.cols;
            this.cols = tmp;           
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Matrix myMatrix = new Matrix(3,4);
            Console.WriteLine("Enter matrix elements:");
            myMatrix.ReadElements();
            Console.WriteLine("Matrix elements are:");
            myMatrix.Show();
            myMatrix.Rotate90DegRight();
            Console.WriteLine("Matrix rotated at 90 deg are:");
            myMatrix.Show();
            Console.ReadLine();
        }
    }
}

Result:

    Enter matrix elements:
    element[0,0]=1
    element[0,1]=2
    element[0,2]=3
    element[0,3]=4
    element[1,0]=5
    element[1,1]=6
    element[1,2]=7
    element[1,3]=8
    element[2,0]=9
    element[2,1]=10
    element[2,2]=11
    element[2,3]=12
    Matrix elements are:
      1  2  3  4
      5  6  7  8
      9 10 11 12
    Matrix rotated at 90 deg are:
      9  5  1
     10  6  2
     11  7  3
     12  8  4
Friedland answered 3/9, 2008 at 20:34 Comment(0)
C
2

From a linear point of view, consider the matrices:

    1 2 3        0 0 1
A = 4 5 6    B = 0 1 0
    7 8 9        1 0 0

Now take A transpose

     1 4 7
A' = 2 5 8
     3 6 9

And consider the action of A' on B, or B on A'.
Respectively:

      7 4 1          3 6 9
A'B = 8 5 2    BA' = 2 5 8
      9 6 3          1 4 7

This is expandable for any n x n matrix. And applying this concept quickly in code:

void swapInSpace(int** mat, int r1, int c1, int r2, int c2)
{
    mat[r1][c1] ^= mat[r2][c2];
    mat[r2][c2] ^= mat[r1][c1];
    mat[r1][c1] ^= mat[r2][c2];
}

void transpose(int** mat, int size)
{
    for (int i = 0; i < size; i++)
    {
        for (int j = (i + 1); j < size; j++)
        {
            swapInSpace(mat, i, j, j, i);
        }
    }
}

void rotate(int** mat, int size)
{
    //Get transpose
    transpose(mat, size);

    //Swap columns
    for (int i = 0; i < size / 2; i++)
    {
        for (int j = 0; j < size; j++)
        {
            swapInSpace(mat, i, j, size - (i + 1), j);
        }
    }
}
Clapboard answered 3/9, 2008 at 20:34 Comment(0)
F
2

Here is the Java version:

public static void rightRotate(int[][] matrix, int n) {
    for (int layer = 0; layer < n / 2; layer++) {
        int first = layer;
        int last = n - 1 - first;
        for (int i = first; i < last; i++) {
           int offset = i - first;
           int temp = matrix[first][i];
           matrix[first][i] = matrix[last-offset][first];
           matrix[last-offset][first] = matrix[last][last-offset];
           matrix[last][last-offset] = matrix[i][last];
           matrix[i][last] = temp;
        }
    }
}

the method first rotate the mostouter layer, then move to the inner layer squentially.

Flatworm answered 3/9, 2008 at 20:34 Comment(0)
U
2

This is my implementation, in C, O(1) memory complexity, in place rotation, 90 degrees clockwise:

#include <stdio.h>

#define M_SIZE 5

static void initMatrix();
static void printMatrix();
static void rotateMatrix();

static int m[M_SIZE][M_SIZE];

int main(void){
    initMatrix();
    printMatrix();
    rotateMatrix();
    printMatrix();

    return 0;
}

static void initMatrix(){
    int i, j;

    for(i = 0; i < M_SIZE; i++){
        for(j = 0; j < M_SIZE; j++){
            m[i][j] = M_SIZE*i + j + 1;
        }
    }
}

static void printMatrix(){
    int i, j;

    printf("Matrix\n");
    for(i = 0; i < M_SIZE; i++){
        for(j = 0; j < M_SIZE; j++){
            printf("%02d ", m[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

static void rotateMatrix(){
    int r, c;

    for(r = 0; r < M_SIZE/2; r++){
        for(c = r; c < M_SIZE - r - 1; c++){
            int tmp = m[r][c];

            m[r][c] = m[M_SIZE - c - 1][r];
            m[M_SIZE - c - 1][r] = m[M_SIZE - r - 1][M_SIZE - c - 1];
            m[M_SIZE - r - 1][M_SIZE - c - 1] = m[c][M_SIZE - r - 1];
            m[c][M_SIZE - r - 1] = tmp;
        }
    }
}
Upturn answered 3/9, 2008 at 20:34 Comment(0)
N
2

PHP:

<?php    
$a = array(array(1,2,3,4),array(5,6,7,8),array(9,0,1,2),array(3,4,5,6));
$b = array(); //result

while(count($a)>0)
{
    $b[count($a[0])-1][] = array_shift($a[0]);
    if (count($a[0])==0)
    {
         array_shift($a);
    }
}

From PHP5.6, Array transposition can be performed with a sleak array_map() call. In other words, columns are converted to rows.

Code: (Demo)

$array = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 0, 1, 2],
    [3, 4, 5, 6]
];
$transposed = array_map(null, ...$array);

$transposed:

[
    [1, 5, 9, 3],
    [2, 6, 0, 4],
    [3, 7, 1, 5],
    [4, 8, 2, 6]
]
Nielson answered 3/9, 2008 at 20:34 Comment(0)
M
1

C code for matrix transpose & rotate (+/-90, +/-180)

  • Supports square and non-square matrices, has in-place and copy features
  • Supports both 2D arrays and 1D pointers with logical rows/cols
  • Unit tests; see tests for examples of usage
  • tested gcc -std=c90 -Wall -pedantic, MSVC17

`

#include <stdlib.h>
#include <memory.h>
#include <assert.h>

/* 
    Matrix transpose & rotate (+/-90, +/-180)
        Supports both 2D arrays and 1D pointers with logical rows/cols
        Supports square and non-square matrices, has in-place and copy features
        See tests for examples of usage
    tested gcc -std=c90 -Wall -pedantic, MSVC17
*/

typedef int matrix_data_t;  /* matrix data type */

void transpose(const matrix_data_t* src, matrix_data_t* dst, int rows, int cols);
void transpose_inplace(matrix_data_t* data, int n );
void rotate(int direction, const matrix_data_t* src, matrix_data_t* dst, int rows, int cols);
void rotate_inplace(int direction, matrix_data_t* data, int n);
void reverse_rows(matrix_data_t* data, int rows, int cols);
void reverse_cols(matrix_data_t* data, int rows, int cols);

/* test/compare fn */
int test_cmp(const matrix_data_t* lhs, const matrix_data_t* rhs, int rows, int cols );

/* TESTS/USAGE */
void transpose_test() {

    matrix_data_t sq3x3[9] = { 0,1,2,3,4,5,6,7,8 };/* 3x3 square, odd length side */
    matrix_data_t sq3x3_cpy[9];
    matrix_data_t sq3x3_2D[3][3] = { { 0,1,2 },{ 3,4,5 },{ 6,7,8 } };/* 2D 3x3 square */
    matrix_data_t sq3x3_2D_copy[3][3];

    /* expected test values */
    const matrix_data_t sq3x3_orig[9] = { 0,1,2,3,4,5,6,7,8 };
    const matrix_data_t sq3x3_transposed[9] = { 0,3,6,1,4,7,2,5,8};

    matrix_data_t sq4x4[16]= { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };/* 4x4 square, even length*/
    const matrix_data_t sq4x4_orig[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
    const matrix_data_t sq4x4_transposed[16] = { 0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15 };

    /* 2x3 rectangle */
    const matrix_data_t r2x3_orig[6] = { 0,1,2,3,4,5 };
    const matrix_data_t r2x3_transposed[6] = { 0,3,1,4,2,5 };
    matrix_data_t r2x3_copy[6];

    matrix_data_t r2x3_2D[2][3] = { {0,1,2},{3,4,5} };  /* 2x3 2D rectangle */
    matrix_data_t r2x3_2D_t[3][2];

    /* matrix_data_t r3x2[6] = { 0,1,2,3,4,5 }; */
    matrix_data_t r3x2_copy[6];
    /* 3x2 rectangle */
    const matrix_data_t r3x2_orig[6] = { 0,1,2,3,4,5 };
    const matrix_data_t r3x2_transposed[6] = { 0,2,4,1,3,5 };

    matrix_data_t r6x1[6] = { 0,1,2,3,4,5 };    /* 6x1 */
    matrix_data_t r6x1_copy[6];

    matrix_data_t r1x1[1] = { 0 };  /*1x1*/
    matrix_data_t r1x1_copy[1];

    /* 3x3 tests, 2D array tests */
    transpose_inplace(sq3x3, 3);    /* transpose in place */
    assert(!test_cmp(sq3x3, sq3x3_transposed, 3, 3));
    transpose_inplace(sq3x3, 3);    /* transpose again */
    assert(!test_cmp(sq3x3, sq3x3_orig, 3, 3));

    transpose(sq3x3, sq3x3_cpy, 3, 3);  /* transpose copy 3x3*/
    assert(!test_cmp(sq3x3_cpy, sq3x3_transposed, 3, 3));

    transpose((matrix_data_t*)sq3x3_2D, (matrix_data_t*)sq3x3_2D_copy, 3, 3);   /* 2D array transpose/copy */
    assert(!test_cmp((matrix_data_t*)sq3x3_2D_copy, sq3x3_transposed, 3, 3));
    transpose_inplace((matrix_data_t*)sq3x3_2D_copy, 3);    /* 2D array transpose in place */
    assert(!test_cmp((matrix_data_t*)sq3x3_2D_copy, sq3x3_orig, 3, 3));

    /* 4x4 tests */
    transpose_inplace(sq4x4, 4);    /* transpose in place */
    assert(!test_cmp(sq4x4, sq4x4_transposed, 4,4));
    transpose_inplace(sq4x4, 4);    /* transpose again */
    assert(!test_cmp(sq4x4, sq4x4_orig, 3, 3));

    /* 2x3,3x2 tests */
    transpose(r2x3_orig, r2x3_copy, 2, 3);
    assert(!test_cmp(r2x3_copy, r2x3_transposed, 3, 2));

    transpose(r3x2_orig, r3x2_copy, 3, 2);
    assert(!test_cmp(r3x2_copy, r3x2_transposed, 2,3));

    /* 2D array */
    transpose((matrix_data_t*)r2x3_2D, (matrix_data_t*)r2x3_2D_t, 2, 3);
    assert(!test_cmp((matrix_data_t*)r2x3_2D_t, r2x3_transposed, 3,2));

    /* Nx1 test, 1x1 test */
    transpose(r6x1, r6x1_copy, 6, 1);
    assert(!test_cmp(r6x1_copy, r6x1, 1, 6));

    transpose(r1x1, r1x1_copy, 1, 1);
    assert(!test_cmp(r1x1_copy, r1x1, 1, 1));

}

void rotate_test() {

    /* 3x3 square */
    const matrix_data_t sq3x3[9] = { 0,1,2,3,4,5,6,7,8 };
    const matrix_data_t sq3x3_r90[9] = { 6,3,0,7,4,1,8,5,2 };
    const matrix_data_t sq3x3_180[9] = { 8,7,6,5,4,3,2,1,0 };
    const matrix_data_t sq3x3_l90[9] = { 2,5,8,1,4,7,0,3,6 };
    matrix_data_t sq3x3_copy[9];

    /* 3x3 square, 2D */
    matrix_data_t sq3x3_2D[3][3] = { { 0,1,2 },{ 3,4,5 },{ 6,7,8 } };

    /* 4x4, 2D */
    matrix_data_t sq4x4[4][4] = { { 0,1,2,3 },{ 4,5,6,7 },{ 8,9,10,11 },{ 12,13,14,15 } };
    matrix_data_t sq4x4_copy[4][4];
    const matrix_data_t sq4x4_r90[16] = { 12,8,4,0,13,9,5,1,14,10,6,2,15,11,7,3 };
    const matrix_data_t sq4x4_l90[16] = { 3,7,11,15,2,6,10,14,1,5,9,13,0,4,8,12 };
    const matrix_data_t sq4x4_180[16] = { 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 };

    matrix_data_t r6[6] = { 0,1,2,3,4,5 };  /* rectangle with area of 6 (1x6,2x3,3x2, or 6x1) */
    matrix_data_t r6_copy[6];
    const matrix_data_t r1x6_r90[6] = { 0,1,2,3,4,5 };
    const matrix_data_t r1x6_l90[6] = { 5,4,3,2,1,0 };
    const matrix_data_t r1x6_180[6] = { 5,4,3,2,1,0 };

    const matrix_data_t r2x3_r90[6] = { 3,0,4,1,5,2 };
    const matrix_data_t r2x3_l90[6] = { 2,5,1,4,0,3 };
    const matrix_data_t r2x3_180[6] = { 5,4,3,2,1,0 };

    const matrix_data_t r3x2_r90[6] = { 4,2,0,5,3,1 };
    const matrix_data_t r3x2_l90[6] = { 1,3,5,0,2,4 };
    const matrix_data_t r3x2_180[6] = { 5,4,3,2,1,0 };

    const matrix_data_t r6x1_r90[6] = { 5,4,3,2,1,0 };
    const matrix_data_t r6x1_l90[6] = { 0,1,2,3,4,5 };
    const matrix_data_t r6x1_180[6] = { 5,4,3,2,1,0 };

    /* sq3x3 tests */
    rotate(90, sq3x3, sq3x3_copy, 3, 3);    /* +90 */
    assert(!test_cmp(sq3x3_copy, sq3x3_r90, 3, 3));
    rotate(-90, sq3x3, sq3x3_copy, 3, 3);   /* -90 */
    assert(!test_cmp(sq3x3_copy, sq3x3_l90, 3, 3));
    rotate(180, sq3x3, sq3x3_copy, 3, 3);   /* 180 */
    assert(!test_cmp(sq3x3_copy, sq3x3_180, 3, 3));
    /* sq3x3 in-place rotations */
    memcpy( sq3x3_copy, sq3x3, 3 * 3 * sizeof(matrix_data_t));
    rotate_inplace(90, sq3x3_copy, 3);
    assert(!test_cmp(sq3x3_copy, sq3x3_r90, 3, 3));
    rotate_inplace(-90, sq3x3_copy, 3);
    assert(!test_cmp(sq3x3_copy, sq3x3, 3, 3)); /* back to 0 orientation */
    rotate_inplace(180, sq3x3_copy, 3);
    assert(!test_cmp(sq3x3_copy, sq3x3_180, 3, 3));
    rotate_inplace(-180, sq3x3_copy, 3);
    assert(!test_cmp(sq3x3_copy, sq3x3, 3, 3));
    rotate_inplace(180, (matrix_data_t*)sq3x3_2D, 3);/* 2D test */
    assert(!test_cmp((matrix_data_t*)sq3x3_2D, sq3x3_180, 3, 3));

    /* sq4x4 */
    rotate(90, (matrix_data_t*)sq4x4, (matrix_data_t*)sq4x4_copy, 4, 4);
    assert(!test_cmp((matrix_data_t*)sq4x4_copy, sq4x4_r90, 4, 4));
    rotate(-90, (matrix_data_t*)sq4x4, (matrix_data_t*)sq4x4_copy, 4, 4);
    assert(!test_cmp((matrix_data_t*)sq4x4_copy, sq4x4_l90, 4, 4));
    rotate(180, (matrix_data_t*)sq4x4, (matrix_data_t*)sq4x4_copy, 4, 4);
    assert(!test_cmp((matrix_data_t*)sq4x4_copy, sq4x4_180, 4, 4));

    /* r6 as 1x6 */
    rotate(90, r6, r6_copy, 1, 6);
    assert(!test_cmp(r6_copy, r1x6_r90, 1, 6));
    rotate(-90, r6, r6_copy, 1, 6);
    assert(!test_cmp(r6_copy, r1x6_l90, 1, 6));
    rotate(180, r6, r6_copy, 1, 6);
    assert(!test_cmp(r6_copy, r1x6_180, 1, 6));

    /* r6 as 2x3 */
    rotate(90, r6, r6_copy, 2, 3);
    assert(!test_cmp(r6_copy, r2x3_r90, 2, 3));
    rotate(-90, r6, r6_copy, 2, 3);
    assert(!test_cmp(r6_copy, r2x3_l90, 2, 3));
    rotate(180, r6, r6_copy, 2, 3);
    assert(!test_cmp(r6_copy, r2x3_180, 2, 3));

    /* r6 as 3x2 */
    rotate(90, r6, r6_copy, 3, 2);
    assert(!test_cmp(r6_copy, r3x2_r90, 3, 2));
    rotate(-90, r6, r6_copy, 3, 2);
    assert(!test_cmp(r6_copy, r3x2_l90, 3, 2));
    rotate(180, r6, r6_copy, 3, 2);
    assert(!test_cmp(r6_copy, r3x2_180, 3, 2));

    /* r6 as 6x1 */
    rotate(90, r6, r6_copy, 6, 1);
    assert(!test_cmp(r6_copy, r6x1_r90, 6, 1));
    rotate(-90, r6, r6_copy, 6, 1);
    assert(!test_cmp(r6_copy, r6x1_l90, 6, 1));
    rotate(180, r6, r6_copy, 6, 1);
    assert(!test_cmp(r6_copy, r6x1_180, 6, 1));
}

/* test comparison fn, return 0 on match else non zero */
int test_cmp(const matrix_data_t* lhs, const matrix_data_t* rhs, int rows, int cols) {

    int r, c;

    for (r = 0; r < rows; ++r) {
        for (c = 0; c < cols; ++c) {
            if ((lhs + r * cols)[c] != (rhs + r * cols)[c])
                return -1;
        }
    }
    return 0;
}

/*
Reverse values in place of each row in 2D matrix data[rows][cols] or in 1D pointer with logical rows/cols
[A B C] ->  [C B A]
[D E F]     [F E D]
*/
void reverse_rows(matrix_data_t* data, int rows, int cols) {

    int r, c;
    matrix_data_t temp;
    matrix_data_t* pRow = NULL;

    for (r = 0; r < rows; ++r) {
        pRow = (data + r * cols);
        for (c = 0; c < (int)(cols / 2); ++c) { /* explicit truncate */
            temp = pRow[c];
            pRow[c] = pRow[cols - 1 - c];
            pRow[cols - 1 - c] = temp;
        }
    }
}

/*
Reverse values in place of each column in 2D matrix data[rows][cols] or in 1D pointer with logical rows/cols
[A B C] ->  [D E F]
[D E F]     [A B C]
*/
void reverse_cols(matrix_data_t* data, int rows, int cols) {

    int r, c;
    matrix_data_t temp;
    matrix_data_t* pRowA = NULL;
    matrix_data_t* pRowB = NULL;

    for (c = 0; c < cols; ++c) {
        for (r = 0; r < (int)(rows / 2); ++r) { /* explicit truncate */
            pRowA = data + r * cols;
            pRowB = data + cols * (rows - 1 - r);
            temp = pRowA[c];
            pRowA[c] = pRowB[c];
            pRowB[c] = temp;
        }
    }
}

/* Transpose NxM matrix to MxN matrix in O(n) time */
void transpose(const matrix_data_t* src, matrix_data_t* dst, int N, int M) {

    int i;
    for (i = 0; i<N*M; ++i) dst[(i%M)*N + (i / M)] = src[i];    /* one-liner version */

    /*
    expanded version of one-liner:  calculate XY based on array index, then convert that to YX array index
    int i,j,x,y;
    for (i = 0; i < N*M; ++i) {
    x = i % M;
    y = (int)(i / M);
    j = x * N + y;
    dst[j] = src[i];
    }
    */

    /*
    nested for loop version
    using ptr arithmetic to get proper row/column
    this is really just dst[col][row]=src[row][col]

    int r, c;

    for (r = 0; r < rows; ++r) {
        for (c = 0; c < cols; ++c) {
            (dst + c * rows)[r] = (src + r * cols)[c];
        }
    }
    */
}

/*
Transpose NxN matrix in place
*/
void transpose_inplace(matrix_data_t* data, int N ) {

    int r, c;
    matrix_data_t temp;

    for (r = 0; r < N; ++r) {
        for (c = r; c < N; ++c) { /*start at column=row*/
                                    /* using ptr arithmetic to get proper row/column */
                                    /* this is really just
                                    temp=dst[col][row];
                                    dst[col][row]=src[row][col];
                                    src[row][col]=temp;
                                    */
            temp = (data + c * N)[r];
            (data + c * N)[r] = (data + r * N)[c];
            (data + r * N)[c] = temp;
        }
    }
}

/*
Rotate 1D or 2D src matrix to dst matrix in a direction (90,180,-90)
Precondition:  src and dst are 2d matrices with dimensions src[rows][cols] and dst[cols][rows] or 1D pointers with logical rows/cols
*/
void rotate(int direction, const matrix_data_t* src, matrix_data_t* dst, int rows, int cols) {

    switch (direction) {
    case -90:
        transpose(src, dst, rows, cols);
        reverse_cols(dst, cols, rows);
        break;
    case 90:
        transpose(src, dst, rows, cols);
        reverse_rows(dst, cols, rows);
        break;
    case 180:
    case -180:
        /* bit copy to dst, use in-place reversals */
        memcpy(dst, src, rows*cols*sizeof(matrix_data_t));
        reverse_cols(dst, cols, rows);
        reverse_rows(dst, cols, rows);
        break;
    }
}

/*
Rotate array in a direction.
Array must be NxN 2D or 1D array with logical rows/cols
Direction can be (90,180,-90,-180)
*/
void rotate_inplace( int direction, matrix_data_t* data, int n) {

    switch (direction) {
    case -90:
        transpose_inplace(data, n);
        reverse_cols(data, n, n);
        break;
    case 90:
        transpose_inplace(data, n);
        reverse_rows(data, n, n);
        break;
    case 180:
    case -180:
        reverse_cols(data, n, n);
        reverse_rows(data, n, n);
        break;
    }
}

`

Maryjomaryl answered 3/9, 2008 at 20:34 Comment(0)
S
1

PHP Solution for clockwise & counterclockwise

$aMatrix = array(
    array( 1, 2, 3 ),
    array( 4, 5, 6 ),
    array( 7, 8, 9 )
    );

function CounterClockwise( $aMatrix )
{
    $iCount  = count( $aMatrix );
    $aReturn = array();
    for( $y = 0; $y < $iCount; ++$y )
    {
        for( $x = 0; $x < $iCount; ++$x )
        {
            $aReturn[ $iCount - $x - 1 ][ $y ] = $aMatrix[ $y ][ $x ];
        }
    }
    return $aReturn;
}

function Clockwise( $aMatrix )
{
    $iCount  = count( $aMatrix );
    $aReturn = array();
    for( $y = 0; $y < $iCount; ++$y )
    {
        for( $x = 0; $x < $iCount; ++$x )
        {
            $aReturn[ $x ][ $iCount - $y - 1 ] = $aMatrix[ $y ][ $x ];
        }
    }
    return $aReturn;
}

function printMatrix( $aMatrix )
{
    $iCount = count( $aMatrix );
    for( $x = 0; $x < $iCount; ++$x )
    {
        for( $y = 0; $y < $iCount; ++$y )
        {
            echo $aMatrix[ $x ][ $y ];
            echo " ";
        }
        echo "\n";
    }
}
printMatrix( $aMatrix );
echo "\n";
$aNewMatrix = CounterClockwise( $aMatrix );
printMatrix( $aNewMatrix );
echo "\n";
$aNewMatrix = Clockwise( $aMatrix );
printMatrix( $aNewMatrix );
Saransarangi answered 3/9, 2008 at 20:34 Comment(0)
C
1

Javascript solution for NxN matrix with runtime O(N^2) and memory O(1)

  function rotate90(matrix){
    var length = matrix.length
    for(var row = 0; row < (length / 2); row++){
      for(var col = row; col < ( length - 1 - row); col++){
        var tmpVal = matrix[row][col];
        for(var i = 0; i < 4; i++){
          var rowSwap = col;
          var colSwap = (length - 1) - row;
          var poppedVal = matrix[rowSwap][colSwap];
          matrix[rowSwap][colSwap] = tmpVal;
          tmpVal = poppedVal;
          col = colSwap;
          row = rowSwap;
        }
      }
    }
  }
Celebrity answered 3/9, 2008 at 20:34 Comment(0)
H
1

here is my In Place implementation in C

void rotateRight(int matrix[][SIZE], int length) {

    int layer = 0;

    for (int layer = 0; layer < length / 2; ++layer) {

        int first = layer;
        int last = length - 1 - layer;

        for (int i = first; i < last; ++i) {

            int topline = matrix[first][i];
            int rightcol = matrix[i][last];
            int bottomline = matrix[last][length - layer - 1 - i];
            int leftcol = matrix[length - layer - 1 - i][first];

            matrix[first][i] = leftcol;
            matrix[i][last] = topline;
            matrix[last][length - layer - 1 - i] = rightcol;
            matrix[length - layer - 1 - i][first] = bottomline;
        }
    }
}
Horrorstruck answered 3/9, 2008 at 20:34 Comment(0)
A
1
private static int[][] rotate(int[][] matrix, int n) {
    int[][] rotated = new int[n][n];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            rotated[i][j] = matrix[n-j-1][i];
        }
    }
    return rotated;
}
Anstus answered 3/9, 2008 at 20:34 Comment(1)
Which language is this in?Precondition
C
1

Here is my attempt for matrix 90 deg rotation which is a 2 step solution in C. First transpose the matrix in place and then swap the cols.

#define ROWS        5
#define COLS        5

void print_matrix_b(int B[][COLS], int rows, int cols) 
{
    for (int i = 0; i <= rows; i++) {
        for (int j = 0; j <=cols; j++) {
            printf("%d ", B[i][j]);
        }
        printf("\n");
    }
}

void swap_columns(int B[][COLS], int l, int r, int rows)
{
    int tmp;
    for (int i = 0; i <= rows; i++) {
        tmp = B[i][l];
        B[i][l] = B[i][r];
        B[i][r] = tmp;
    }
}


void matrix_2d_rotation(int B[][COLS], int rows, int cols)
{
    int tmp;
    // Transpose the matrix first
    for (int i = 0; i <= rows; i++) {
        for (int j = i; j <=cols; j++) {
            tmp = B[i][j];
            B[i][j] = B[j][i];
            B[j][i] = tmp;
        }
    }
    // Swap the first and last col and continue until
    // the middle.
    for (int i = 0; i < (cols / 2); i++)
        swap_columns(B, i, cols - i, rows);
}



int _tmain(int argc, _TCHAR* argv[])
{
    int B[ROWS][COLS] = { 
                  {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}
                        };

    matrix_2d_rotation(B, ROWS - 1, COLS - 1);

    print_matrix_b(B, ROWS - 1, COLS -1);
    return 0;
}
Coronation answered 3/9, 2008 at 20:34 Comment(0)
D
1

C code for matrix rotation 90 degree clockwise IN PLACE for any M*N matrix

void rotateInPlace(int * arr[size][size], int row, int column){
    int i, j;
    int temp = row>column?row:column;
    int flipTill = row < column ? row : column;
    for(i=0;i<flipTill;i++){
        for(j=0;j<i;j++){
            swapArrayElements(arr, i, j);
        }
    }

    temp = j+1;

    for(i = row>column?i:0; i<row; i++){
            for(j=row<column?temp:0; j<column; j++){
                swapArrayElements(arr, i, j);
            }
    }

    for(i=0;i<column;i++){
        for(j=0;j<row/2;j++){
            temp = arr[i][j];
            arr[i][j] = arr[i][row-j-1];
            arr[i][row-j-1] = temp;
        }
    }
}
Disputable answered 3/9, 2008 at 20:34 Comment(0)
X
1

#transpose is a standard method of Ruby's Array class, thus:

% irb
irb(main):001:0> m = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 1, 2], [3, 4, 5, 6]]
=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 1, 2], [3, 4, 5, 6]] 
irb(main):002:0> m.reverse.transpose
=> [[3, 9, 5, 1], [4, 0, 6, 2], [5, 1, 7, 3], [6, 2, 8, 4]]

The implementation is an n^2 transposition function written in C. You can see it here: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-transpose by choosing "click to toggle source" beside "transpose".

I recall better than O(n^2) solutions, but only for specially constructed matrices (such as sparse matrices)

Xylophone answered 3/9, 2008 at 20:34 Comment(0)
A
1

For i:= 0 to X do For j := 0 to X do graphic[j][i] := graphic2[X-i][j]

X is the size of the array the graphic is in.

Astrogeology answered 3/9, 2008 at 20:34 Comment(0)
A
1
short normal[4][4] = {{8,4,7,5},{3,4,5,7},{9,5,5,6},{3,3,3,3}};

short rotated[4][4];

for (int r = 0; r < 4; ++r)
{
  for (int c = 0; c < 4; ++c)
  {
    rotated[r][c] = normal[c][3-r];
  }
}

Simple C++ method, tho there would be a big memory overhead in a big array.

Agleam answered 3/9, 2008 at 20:34 Comment(1)
Among all of these answers I've found and tested this one that is compact and enough to rotateAdvanced
H
1

@dagorym: Aw, man. I had been hanging onto this as a good "I'm bored, what can I ponder" puzzle. I came up with my in-place transposition code, but got here to find yours pretty much identical to mine...ah, well. Here it is in Ruby.

require 'pp'
n = 10
a = []
n.times { a << (1..n).to_a }

pp a

0.upto(n/2-1) do |i|
  i.upto(n-i-2) do |j|
    tmp             = a[i][j]
    a[i][j]         = a[n-j-1][i]
    a[n-j-1][i]     = a[n-i-1][n-j-1]
    a[n-i-1][n-j-1] = a[j][n-i-1]
    a[j][n-i-1]     = tmp
  end
end

pp a
Hexapla answered 3/9, 2008 at 20:34 Comment(0)
D
0

In Eigen (C++):

Eigen::Matrix2d mat;
mat <<  1, 2,
        3, 4;
std::cout << mat << "\n\n";

Eigen::Matrix2d r_plus_90 = mat.transpose().rowwise().reverse();
std::cout << r_plus_90 << "\n\n";

Eigen::Matrix2d r_minus_90 = mat.transpose().colwise().reverse();
std::cout << r_minus_90 << "\n\n";

Eigen::Matrix2d r_180 = mat.colwise().reverse().rowwise().reverse(); // +180 same as -180
std::cout << r_180 << "\n\n";

Output:

1 2
3 4

3 1
4 2

2 4
1 3

4 3
2 1
Disc answered 3/9, 2008 at 20:34 Comment(0)
L
0

I was able to do this with a single loop. The time complexity seems like O(K) where K is all items of the array. Here's how I did it in JavaScript:

First off, we represent the n^2 matrix with a single array. Then, iterate through it like this:

/**
 * Rotates matrix 90 degrees clockwise
 * @param arr: the source array
 * @param n: the array side (array is square n^2)
 */
function rotate (arr, n) {
  var rotated = [], indexes = []

  for (var i = 0; i < arr.length; i++) {
    if (i < n)
      indexes[i] = i * n + (n - 1)
    else
      indexes[i] = indexes[i - n] - 1

    rotated[indexes[i]] = arr[i]
  }
  return rotated
}

Basically, we transform the source array indexes:

[0,1,2,3,4,5,6,7,8] => [2,5,8,1,4,7,0,3,6]

Then, using this transformed indexes array, we place the actual values in the final rotated array.

Here are some test cases:

//n=3
rotate([
  1, 2, 3,
  4, 5, 6,
  7, 8, 9], 3))

//result:
[7, 4, 1,
 8, 5, 2,
 9, 6, 3]


//n=4
rotate([
  1,  2,  3,  4,
  5,  6,  7,  8,
  9,  10, 11, 12,
  13, 14, 15, 16], 4))

//result:
[13,  9,  5,  1,
 14, 10,  6,  2,
 15, 11,  7,  3,
 16, 12,  8,  4]


//n=5
rotate([
  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], 5))

//result:
[21, 16, 11,  6,  1, 
 22, 17, 12,  7,  2, 
 23, 18, 13,  8,  3, 
 24, 19, 14,  9,  4, 
 25, 20, 15, 10,  5]
Lorola answered 3/9, 2008 at 20:34 Comment(2)
This is still technically n^2 since k = n^2. But great idea though, and I'm pretty sure n^2 is the minimum time complexity to rotate a 2d array.Hammond
This is a futile answer. OP has a 2d array but you're assuming the array is given as a single array instead of a 2d array or an array of arrays. Even if you want to create a single array from a 2d array you're bound to read every element which is n^2 time complexity anyway.Pursuit
K
0

This solution doesn't care square or rectangle dimension, you can rotate 4x5 or 5x4 or even 4x4, it doesn't care the size as well. Note that this implementation creates a new array every time you call rotate90 method, it doesn't mutate the original array at all.

public static void main(String[] args) {
    int[][] a = new int[][] { 
                    { 1, 2, 3, 4 }, 
                    { 5, 6, 7, 8 }, 
                    { 9, 0, 1, 2 }, 
                    { 3, 4, 5, 6 }, 
                    { 7, 8, 9, 0 } 
                  };
    int[][] rotate180 = rotate90(rotate90(a));
    print(rotate180);
}

static int[][] rotate90(int[][] a) {
    int[][] ret = new int[a[0].length][a.length];
    for (int i = 0; i < a.length; i++) {
        for (int j = 0; j < a[i].length; j++) {
            ret[j][a.length - i - 1] = a[i][j];
        }
    }
    return ret;
}

static void print(int[][] array) {
    for (int i = 0; i < array.length; i++) {
        System.out.print("[");
        for (int j = 0; j < array[i].length; j++) {
            System.out.print(array[i][j]);
            System.out.print(" ");
        }
        System.out.println("]");
    }
}
Keesee answered 3/9, 2008 at 20:34 Comment(0)
C
0

Based on the community wiki algorithm and this SO answer for transposing arrays, here is a Swift 4 version to rotate some 2D array 90 degrees counter-clockwise. This assumes matrix is a 2D array:

func rotate(matrix: [[Int]]) -> [[Int]] {
    let transposedPoints = transpose(input: matrix)
    let rotatedPoints = transposedPoints.map{ Array($0.reversed()) }
    return rotatedPoints
}


fileprivate func transpose<T>(input: [[T]]) -> [[T]] {
    if input.isEmpty { return [[T]]() }
    let count = input[0].count
    var out = [[T]](repeating: [T](), count: count)
    for outer in input {
        for (index, inner) in outer.enumerated() {
            out[index].append(inner)
        }
    }

    return out
}
Cress answered 3/9, 2008 at 20:34 Comment(0)
L
0

Based on the plethora of other answers, I came up with this in C#:

/// <param name="rotation">The number of rotations (if negative, the <see cref="Matrix{TValue}"/> is rotated counterclockwise; 
/// otherwise, it's rotated clockwise). A single (positive) rotation is equivalent to 90° or -270°; a single (negative) rotation is 
/// equivalent to -90° or 270°. Matrices may be rotated by 90°, 180°, or 270° only (or multiples thereof).</param>
/// <returns></returns>
public Matrix<TValue> Rotate(int rotation)
{
    var result = default(Matrix<TValue>);

    //This normalizes the requested rotation (for instance, if 10 is specified, the rotation is actually just +-2 or +-180°, but all 
    //correspond to the same rotation).
    var d = rotation.ToDouble() / 4d;
    d = d - (int)d;

    var degree = (d - 1d) * 4d;

    //This gets the type of rotation to make; there are a total of four unique rotations possible (0°, 90°, 180°, and 270°).
    //Each correspond to 0, 1, 2, and 3, respectively (or 0, -1, -2, and -3, if in the other direction). Since
    //1 is equivalent to -3 and so forth, we combine both cases into one. 
    switch (degree)
    {
        case -3:
        case +1:
            degree = 3;
            break;
        case -2:
        case +2:
            degree = 2;
            break;
        case -1:
        case +3:
            degree = 1;
            break;
        case -4:
        case  0:
        case +4:
            degree = 0;
            break;
    }
    switch (degree)
    {
        //The rotation is 0, +-180°
        case 0:
        case 2:
            result = new TValue[Rows, Columns];
            break;
        //The rotation is +-90°
        case 1:
        case 3:
            result = new TValue[Columns, Rows];
            break;
    }

    for (uint i = 0; i < Columns; ++i)
    {
        for (uint j = 0; j < Rows; ++j)
        {
            switch (degree)
            {
                //If rotation is 0°
                case 0:
                    result._values[j][i] = _values[j][i];
                    break;
                //If rotation is -90°
                case 1:
                    //Transpose, then reverse each column OR reverse each row, then transpose
                    result._values[i][j] = _values[j][Columns - i - 1];
                    break;
                //If rotation is +-180°
                case 2:
                    //Reverse each column, then reverse each row
                    result._values[(Rows - 1) - j][(Columns - 1) - i] = _values[j][i];
                    break;
                //If rotation is +90°
                case 3:
                    //Transpose, then reverse each row
                    result._values[i][j] = _values[Rows - j - 1][i];
                    break;
            }
        }
    }
    return result;
}

Where _values corresponds to a private two-dimensional array defined by Matrix<TValue> (in the form of [][]). result = new TValue[Columns, Rows] is possible via implicit operator overload and converts the two-dimensional array to Matrix<TValue>. The two properties Columns and Rows are public properties that get the number of columns and rows of the current instance:

public uint Columns 
    => (uint)_values[0].Length;

public uint Rows 
    => (uint)_values.Length;

Assuming, of course, that you prefer to work with unsigned indices ;-)

All of this allows you to specify how many times it should be rotated and whether it should be rotated left (if less than zero) or right (if greater than zero). You can improve this to check for rotation in actual degrees, but then you'd want to throw an exception if the value isn't a multiple of 90. With that input, you could change the method accordingly:

public Matrix<TValue> Rotate(int rotation)
{
    var _rotation = (double)rotation / 90d;

    if (_rotation - Math.Floor(_rotation) > 0)
    {
        throw new NotSupportedException("A matrix may only be rotated by multiples of 90.").
    }

    rotation = (int)_rotation;
    ...
}

Since a degree is more accurately expressed by double than int, but a matrix can only rotate in multiples of 90, it is far more intuitive to make the argument correspond to something else that can be accurately represented by the data structure used. int is perfect because it can tell you how many times to rotate it up to a certain unit (90) as well as the direction. double may very well be able to tell you that also, but it also includes values that aren't supported by this operation (which is inherently counter-intuitive).

Lollygag answered 3/9, 2008 at 20:34 Comment(0)
H
0

Here is a Javascript solution:

const transpose = m => m[0].map((x,i) => m.map(x => x[i]));

a: // original matrix
123
456
789

transpose(a).reverse(); // rotate 90 degrees counter clockwise 
369
258
147

transpose(a.slice().reverse()); // rotate 90 degrees clockwise 
741
852
963

transpose(transpose(a.slice().reverse()).slice().reverse())
// rotate 180 degrees 
987
654
321
Hourigan answered 3/9, 2008 at 20:34 Comment(0)
S
0

My version of rotation:

void rotate_matrix(int *matrix, int size)
{

int result[size*size];

    for (int i = 0; i < size; ++i)
        for (int j = 0; j < size; ++j)
            result[(size - 1 - i) + j*size] = matrix[i*size+j];

    for (int i = 0; i < size*size; ++i)
        matrix[i] = result[i];
}

In it we change last column to first row and so further. It is may be not optimal but clear for understanding.

Splendid answered 3/9, 2008 at 20:34 Comment(0)
S
0

Here is a recursive PHP way:

$m = array();
            $m[0] = array('a', 'b', 'c');
            $m[1] = array('d', 'e', 'f');
            $m[2] = array('g', 'h', 'i');
            $newMatrix = array();

            function rotateMatrix($m, $i = 0, &$newMatrix)
            {
                foreach ($m as $chunk) {
                    $newChunk[] = $chunk[$i];
                }
                $newMatrix[] = array_reverse($newChunk);
                $i++;

                if ($i < count($m)) {
                    rotateMatrix($m, $i, $newMatrix);
                }
            }

            rotateMatrix($m, 0, $newMatrix);
            echo '<pre>';
            var_dump($newMatrix);
            echo '<pre>';
Splitting answered 3/9, 2008 at 20:34 Comment(0)
D
0

All the current solutions have O(n^2) overhead as scratch space (this excludes those filthy OOP cheaters!). Here's a solution with O(1) memory usage, rotating the matrix in-place 90 degress right. Screw extensibility, this sucker runs fast!

#include <algorithm>
#include <cstddef>

// Rotates an NxN matrix of type T 90 degrees to the right.
template <typename T, size_t N>
void rotate_matrix(T (&matrix)[N][N])
{
    for(size_t i = 0; i < N; ++i)
        for(size_t j = 0; j <= (N-i); ++j)
            std::swap(matrix[i][j], matrix[j][i]);
}

DISCLAIMER: I didn't actually test this. Let's play whack-a-bug!

Directorial answered 3/9, 2008 at 20:34 Comment(1)
Doesn't this just transpose the matrix, not rotate it?Doridoria
A
0
#include <iostream>
#include <iomanip>

using namespace std;
const int SIZE=3;
void print(int a[][SIZE],int);
void rotate(int a[][SIZE],int);

void main()
{
    int a[SIZE][SIZE]={{11,22,33},{44,55,66},{77,88,99}};
    cout<<"the array befor rotate\n";

    print(a,SIZE);
    rotate( a,SIZE);
    cout<<"the array after rotate\n";
    print(a,SIZE);
    cout<<endl;

}

void print(int a[][SIZE],int SIZE)
{
    int i,j;
    for(i=0;i<SIZE;i++)
       for(j=0;j<SIZE;j++)
          cout<<a[i][j]<<setw(4);
}

void rotate(int a[][SIZE],int SIZE)
{
    int temp[3][3],i,j;
    for(i=0;i<SIZE;i++)
       for(j=0;j<SIZE/2.5;j++)
       {
           temp[i][j]= a[i][j];
           a[i][j]= a[j][SIZE-i-1] ;
           a[j][SIZE-i-1] =temp[i][j];

       }
}
Aves answered 3/9, 2008 at 20:34 Comment(0)
B
-1

In Java

public class Matrix {
/* Author Shrikant Dande */
private static void showMatrix(int[][] arr,int rows,int col){

    for(int i =0 ;i<rows;i++){
        for(int j =0 ;j<col;j++){
            System.out.print(arr[i][j]+" ");
        }
        System.out.println();
    }

}

private static void rotateMatrix(int[][] arr,int rows,int col){

    int[][] tempArr = new int[4][4];
    for(int i =0 ;i<rows;i++){
        for(int j =0 ;j<col;j++){
            tempArr[i][j] = arr[rows-1-j][i];
            System.out.print(tempArr[i][j]+" ");
        }
        System.out.println();
    }

}
public static void main(String[] args) {
    int[][] arr = { {1,  2,  3,  4},
             {5,  6,  7,  8},
             {9,  1, 2, 5},
             {7, 4, 8, 9}};
    int rows = 4,col = 4;

    showMatrix(arr, rows, col);
    System.out.println("------------------------------------------------");
    rotateMatrix(arr, rows, col);

}

}

Beldam answered 3/9, 2008 at 20:34 Comment(0)
O
-1

Can be done recursively quite cleanly, here is my implementation in golang!

rotate nxn matrix in go golang recursively in place with no additional memory

func rot90(a [][]int) {
    n := len(a)
    if n == 1 {
        return
    }
    for i := 0; i < n; i++ {
        a[0][i], a[n-1-i][n-1] = a[n-1-i][n-1], a[0][i]
    }
    rot90(a[1:])
}
Ossiferous answered 3/9, 2008 at 20:34 Comment(0)
T
-1
    public static void rotateMatrix(int[,] matrix)
    {
        //C#, to rotate an N*N matrix in place
        int n = matrix.GetLength(0);
        int layers =  n / 2;
        int temp, temp2;

        for (int i = 0; i < layers; i++) // for a 5 * 5 matrix, layers will be 2, since at layer three there would be only one element, (2,2), and we do not need to rotate it with itself 
        {
            int offset = 0;
            while (offset < n - 2 * i - 1)
            {
                // top right <- top left 
                temp = matrix[i + offset, n - i - 1]; //top right value when offset is zero
                matrix[i + offset, n - i - 1] = matrix[i, i + offset];   

                //bottom right <- top right 
                temp2 = matrix[n - i - 1, n - i - 1 - offset]; //bottom right value when offset is zero
                matrix[n - i - 1, n - i - 1 - offset] = temp;  

                //bottom left <- bottom right 
                temp = matrix[n - i - 1 - offset, i];
                matrix[n - i - 1 - offset, i] = temp2;  

                //top left <- bottom left 
                matrix[i, i + offset] = temp; 

                offset++;
            }
        }
    }
Torrance answered 3/9, 2008 at 20:34 Comment(0)
E
-1

Here is a C# static generic method that does the work for you. Variables are well-named, so you can easily catch the idea of the algorythm.

private static T[,] Rotate180 <T> (T[,] matrix)
{
    var height = matrix.GetLength (0);
    var width = matrix.GetLength (1);
    var answer = new T[height, width];

    for (int y = 0; y < height / 2; y++)
    {
        int topY = y;
        int bottomY = height - 1 - y;
        for (int topX = 0; topX < width; topX++)
        {
            var bottomX = width - topX - 1;
            answer[topY, topX] = matrix[bottomY, bottomX];
            answer[bottomY, bottomX] = matrix[topY, topX];
        }
    }

    if (height % 2 == 0)
        return answer;

    var centerY = height / 2;
    for (int leftX = 0; leftX < Mathf.CeilToInt(width / 2f); leftX++)
    {
        var rightX = width - 1 - leftX;
        answer[centerY, leftX] = matrix[centerY, rightX];
        answer[centerY, rightX] = matrix[centerY, leftX];
    }

    return answer;
}
Endblown answered 3/9, 2008 at 20:34 Comment(0)
H
-1

My C# example code for the great Algorithm sent by @dimple:

/* Author: Dudi,
 * http://www.tutorialspoint.com/compile_csharp_online.php?PID=0Bw_CjBb95KQMYm5qU3VjVGNuZFU */

using System.IO;
using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Rotating this matrix by 90+ degree:");

        int[,] values=new int[3,3]{{1,2,3}, {4,5,6}, {7,8,9}};
        //int[,] values=new int[4,4]{{101,102,103, 104}, {105,106, 107,108}, {109, 110, 111, 112}, {113, 114, 115, 116}};

        print2dArray(ref values);
        transpose2dArray(ref values);
        //print2dArray(ref values);
        reverse2dArray(ref values);
        Console.WriteLine("Output:");
        print2dArray(ref values);
    }

    static void print2dArray(ref int[,] matrix){
        int  nLen = matrix.GetLength(0);
        int  mLen = matrix.GetLength(1);    
        for(int n=0; n<nLen; n++){
            for(int m=0; m<mLen; m++){
                Console.Write(matrix[n,m] +"\t");
            }
            Console.WriteLine();        
        }
        Console.WriteLine();
    }

    static void transpose2dArray(ref int[,] matrix){
        int  nLen = matrix.GetLength(0);
        int  mLen = matrix.GetLength(1);    
        for(int n=0; n<nLen; n++){
            for(int m=0; m<mLen; m++){
                if(n>m){
                    int tmp = matrix[n,m];
                    matrix[n,m] = matrix[m,n];
                    matrix[m,n] = tmp;
                }
            }
        }
    }

    static void reverse2dArray(ref int[,] matrix){
        int  nLen = matrix.GetLength(0);
        int  mLen = matrix.GetLength(1);
        for(int n=0; n<nLen; n++){
            for(int m=0; m<mLen/2; m++){                
                int tmp = matrix[n,m];
                matrix[n,m] = matrix[n, mLen-1-m];
                matrix[n,mLen-1-m] = tmp;
            }
        }
    }
}

/*
Rotating this matrix by 90+ degree:                                                                                                                                             
1       2       3                                                                                                                                                               
4       5       6                                                                                                                                                               
7       8       9                                                                                                                                                               

Output:                                                                                                                                                                         
7       4       1                                                                                                                                                               
8       5       2                                                                                                                                                               
9       6       3  
*/
Haemal answered 3/9, 2008 at 20:34 Comment(2)
I didn't understand you?Haemal
(Compare versions. Won't go into whitespace&commas/operators or not using a swap primitive.)Despotism
L
-1

This is simple C code to rotate an array 90degrees. Hope this helps.

#include <stdio.h>

void main(){
int arr[3][4] =     {85, 2, 85,  4,
                     85, 6,  7, 85,
                     9, 85, 11, 12};


int arr1[4][3];

int i = 0, j = 0;

for(i=0;i<4;i++){
int k = 2;//k = (number of columns in the new array arr1 - 1)
for(j=0;j<3;j++){
arr1[i][j]=arr[k][i];
k--;
}
}

int l, m;
for(l=0;l<4;l++){
for(m=0;m<3;m++){
printf("%d ", arr1[l][m]);
}
printf("\n");
}
}//end main
Lefton answered 3/9, 2008 at 20:34 Comment(0)
A
-1

Here it is in Java:

public static void rotateInPlace(int[][] m) {
    for(int layer = 0; layer < m.length/2; layer++){
        int first = layer;
        int last = m.length - 1 - first;
        for(int i = first; i < last; i ++){
            int offset = i - first;
            int top = m[first][i];
            m[first][i] = m[last - offset][first];
            m[last - offset][first] = m[last][last - offset];
            m[last][last - offset] = m[i][last];
            m[i][last] = top;
        }
    }
}
Archy answered 3/9, 2008 at 20:34 Comment(0)
H
-1

This is an overrated interview question these days.

My suggestion is: Do not let the interviewer confuse you with their crazy suggestion about solving this problem. Use the whiteboard to draw the indexing of input array then draw the indexing of output array. Samples of column indexing before and after rotation shown below:

30 --> 00
20 --> 01
10 --> 02
00 --> 03

31 --> 10
21 --> 11
11 --> 12
01 --> 13

Notice the number pattern after rotation.

Provided below a clean cut Java solution. It is tested, and it works:

 Input:
    M A C P 
    B N L D 
    Y E T S 
    I W R Z 

    Output:
    I Y B M 
    W E N A 
    R T L C 
    Z S D P 

/**
 * (c) @author "G A N MOHIM"
 * Oct 3, 2015
 * RotateArrayNintyDegree.java
 */
package rotatearray;

public class RotateArrayNintyDegree {

    public char[][] rotateArrayNinetyDegree(char[][] input) {
        int k; // k is used to generate index for output array

        char[][] output = new char[input.length] [input[0].length];

        for (int i = 0; i < input.length; i++) {
            k = 0;
            for (int j = input.length-1; j >= 0; j--) {
                output[i][k] = input[j][i]; // note how i is used as column index, and j as row
                k++;
            }
        }

        return output;
    }

    public void printArray(char[][] charArray) {
        for (int i = 0; i < charArray.length; i++) {
            for (int j = 0; j < charArray[0].length; j++) {
                System.out.print(charArray[i][j] + " ");
            }
            System.out.println();
        }


    }

    public static void main(String[] args) {
        char[][] input = 
                { {'M', 'A', 'C', 'P'},
                  {'B', 'N', 'L', 'D'},
                  {'Y', 'E', 'T', 'S'},
                  {'I', 'W', 'R', 'Z'}
                };

        char[][] output = new char[input.length] [input[0].length];

        RotateArrayNintyDegree rotationObj = new RotateArrayNintyDegree();
        rotationObj.printArray(input);

        System.out.println("\n");
        output = rotationObj.rotateArrayNinetyDegree(input);
        rotationObj.printArray(output);

    }

}
Higgs answered 3/9, 2008 at 20:34 Comment(1)
Not an in-place solution.Accessible
W
-1

In place clock wise 90 degrees rotation using vector of vectors..

 #include<iostream>
 #include<vector>
 #include<algorithm>
 using namespace std;
 //Rotate a Matrix by 90 degrees
void rotateMatrix(vector<vector<int> > &matrix){
   int n=matrix.size();
   for(int i=0;i<n;i++){
    for(int j=i+1;j<n;j++){
        swap(matrix[i][j],matrix[j][i]);
    }
 }
     for(int i=0;i<n;i++){
        reverse(matrix[i].begin(),matrix[i].end());
       }
   }

    int main(){

   int n;
   cout<<"enter the size of the matrix:"<<endl;
     while (cin >> n) {
    vector< vector<int> > m;
      cout<<"enter the elements"<<endl;
    for (int i = 0; i < n; i++) {
        m.push_back(vector<int>(n));
        for (int j = 0; j < n; j++)
            scanf("%d", &m[i][j]);
    }
      cout<<"the rotated matrix is:"<<endl;
      rotateMatrix(m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            cout << m[i][j] << ' ';
        cout << endl;
    }
   }
   return 0;
 }
Washedup answered 3/9, 2008 at 20:34 Comment(0)
P
-1
/* 90-degree clockwise:
   temp_array         = left_col
   left_col           = bottom_row
   bottom_row         = reverse(right_col)
   reverse(right_col) = reverse(top_row)
   reverse(top_row)   = temp_array
*/
void RotateClockwise90(int ** arr, int lo, int hi) {

  if (lo >= hi) 
    return;

  for (int i=lo; i<hi; i++) {
    int j = lo+hi-i;
    int temp   = arr[i][lo];
    arr[i][lo] = arr[hi][i];
    arr[hi][i] = arr[j][hi];
    arr[j][hi] = arr[lo][j];
    arr[lo][j] = temp;
  }

  RotateClockwise90(arr, lo+1, hi-1);
}
Pagan answered 3/9, 2008 at 20:34 Comment(0)
M
-1

JavaScript solution to rotate matrix by 90 degrees in place:

function rotateBy90(m) {
  var length = m.length;
  //for each layer of the matrix
  for (var first = 0; first < length >> 1; first++) {
    var last = length - 1 - first;
    for (var i = first; i < last; i++) {
      var top = m[first][i]; //store top
      m[first][i] = m[last - i][first]; //top = left
      m[last - i][first] = m[last][last - i]; //left = bottom
      m[last][last - i] = m[i][last]; //bottom = right
      m[i][last] = top; //right = top
    }
  }
  return m;
}
Mesentery answered 3/9, 2008 at 20:34 Comment(0)
H
-1

PHP:

array_unshift($array, null);
$array = call_user_func_array("array_map", $array);

If you need to rotate rectangular two-dimension array on 90 degree, add the following line before or after (depending on the rotation direction you need) the code above:

$array = array_reverse($array);
Hanforrd answered 3/9, 2008 at 20:34 Comment(0)
O
-1
#!/usr/bin/env python

original = [ [1,2,3],
             [4,5,6],
             [7,8,9] ]

# Rotate matrix 90 degrees...
for i in map(None,*original[::-1]):
    print str(i) + '\n'

This causes the sides to be rotated 90 degrees (ie. 123 (top side) is now 741 (left side).

This Python solution works because it uses slicing with a negative step to reverse the row orders (bringing 7 to top)

original = [ [7,8,9],
             [4,5,6],
             [1,2,3] ]

It then uses map (along with the implied identity function which is the result of map with None as first arg) along with * to unpack all elements in sequence, to regroup the columns (ie. the first elements are put in a tuple together, the 2nd elements are put in a tuple together, and so forth). You effectively get get returned the following regrouping:

original = [[7,8,9],
             [4,5,6],
             [1,2,3]]
Odell answered 3/9, 2008 at 20:34 Comment(1)
map(None, ... is not supported in Python 3, and in both Py 2 and Py 3, the better approach would be to replace map(None, *original[::-1]) with zip(*original[::-1]), which accomplishes the same thing when all rows are the same length without trying to handle a transform function.Barone
N
-1

For Novice programmers, in plain C++ . (Borland stuff)

#include<iostream.h>
#include<conio.h>

int main()
{
    clrscr();

    int arr[10][10];        // 2d array that holds input elements 
    int result[10][10];     //holds result

    int m,n;                //rows and columns of arr[][]
    int x,y;                //rows and columns of result[][]

    int i,j;                //loop variables
    int t;                  //temporary , holds data while conversion

    cout<<"Enter no. of rows and columns of array: ";
    cin>>m>>n;
    cout<<"\nEnter elements of array: \n\n";
    for(i = 0; i < m; i++)
    {
        for(j = 0; j<n ; j++)
        {
          cin>>arr[i][j];         // input array elements from user
        }
    }


   //rotating matrix by +90 degrees

    x = n ;                      //for non-square matrix
    y = m ;     

    for(i = 0; i < x; i++)
    {  t = m-1;                     // to create required array bounds
       for(j = 0; j < y; j++)
       {
          result[i][j] = arr[t][i];
          t--;
       }
   }

   //print result

   cout<<"\nRotated matrix is: \n\n";
   for(i = 0; i < x; i++)
   {
       for(j = 0; j < y; j++)
       {
             cout<<result[i][j]<<" ";
       }
       cout<<"\n";
   }

   getch();
   return 0;
}
Nicknickel answered 3/9, 2008 at 20:34 Comment(0)
S
-1

It is not possible to do it quicker than O(n^2) for in place rotation, for the reason that if we want to rotate the matrix, we have to touch all the n^2 element at least once, no matter what algorithm you are implementing.

Shea answered 3/9, 2008 at 20:34 Comment(1)
In this case n should refer to the number of elements in the matrix, not the length of one of its sides, making matrix rotation O(n) (i.e. linear)Yhvh
I
-2

Try My library abacus-common:

@Test
public void test_42519() throws Exception {
    final IntMatrix matrix = IntMatrix.range(0, 16).reshape(4);

    N.println("======= original =======================");
    matrix.println();
    // print out:
    //    [0, 1, 2, 3]
    //    [4, 5, 6, 7]
    //    [8, 9, 10, 11]
    //    [12, 13, 14, 15]

    N.println("======= rotate 90 ======================");
    matrix.rotate90().println();
    // print out:
    //    [12, 8, 4, 0]
    //    [13, 9, 5, 1]
    //    [14, 10, 6, 2]
    //    [15, 11, 7, 3]

    N.println("======= rotate 180 =====================");
    matrix.rotate180().println();
    // print out:
    //    [15, 14, 13, 12]
    //    [11, 10, 9, 8]
    //    [7, 6, 5, 4]
    //    [3, 2, 1, 0]

    N.println("======= rotate 270 ======================");
    matrix.rotate270().println();
    // print out:
    //    [3, 7, 11, 15]
    //    [2, 6, 10, 14]
    //    [1, 5, 9, 13]
    //    [0, 4, 8, 12]

    N.println("======= transpose =======================");
    matrix.transpose().println();
    // print out:
    //    [0, 4, 8, 12]
    //    [1, 5, 9, 13]
    //    [2, 6, 10, 14]
    //    [3, 7, 11, 15]

    final IntMatrix bigMatrix = IntMatrix.range(0, 10000_0000).reshape(10000);

    // It take about 2 seconds to rotate 10000 X 10000 matrix.
    Profiler.run(1, 2, 3, "sequential", () -> bigMatrix.rotate90()).printResult();

    // Want faster? Go parallel. 1 second to rotate 10000 X 10000 matrix.
    final int[][] a = bigMatrix.array();
    final int[][] c = new int[a[0].length][a.length];
    final int n = a.length;
    final int threadNum = 4;

    Profiler.run(1, 2, 3, "parallel", () -> {
        IntStream.range(0, n).parallel(threadNum).forEach(i -> {
            for (int j = 0; j < n; j++) {
                c[i][j] = a[n - j - 1][i];
            }
        });
    }).printResult();
}
Intoxicative answered 3/9, 2008 at 20:34 Comment(0)
M
-2

The O(1) memory algorithm:

  1. rotate the outer-most data, then you can get below result:

    [3][9][5][1]
    [4][6][7][2]
    [5][0][1][3]
    [6][2][8][4]
    

To do this rotation, we know

    dest[j][n-1-i] = src[i][j]

Observe below: a(0,0) -> a(0,3) a(0,3) -> a(3,3) a(3,3) -> a(3,0) a(3,0) -> a(0,0)

Therefore it's a circle, you can rotate N elements in one loop. Do this N-1 loop then you can rotate the outer-most elements.

  1. Now you can the inner is a same question for 2X2.

Therefore we can conclude it like below:

function rotate(array, N)
{
    Rotate outer-most data
    rotate a new array with N-2 or you can do the similar action following step1
}
Moneymaker answered 3/9, 2008 at 20:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.