Husain
Husain

Reputation: 65

matrix 90 degree clockwise rotation using list in python

I'm trying to rotate a 3*3 matrix clockwise 90 degrees in python. I've identified that element at [ i ][ j ] goes to [ j ][ new_i ]. Here new_i depends upon the previous i, so i made a function for it called circular subtraction.

if i is 0 then new_i is 2

if i is 1 then new_i is 1

if i is 2 then new_i is 0

after execution, it gave me unexpected results.

I've printed everything that is happening in each iteration. I am unable to figure out how some elements are getting replaced with different ones.

'''
1 2 3                       7 4 1
4 5 6  rotate 90 degrees    8 5 2
7 8 9                       9 6 3


'''

def circular_subtraction(i):
    new_i = i 
    if(i==0):
        new_i = 2
    elif(i==1):
        new_i = 1
    elif(i==2):
        new_i = 0
    return new_i


def rotate_clock(matrix):
    new_matrix = matrix

for i in range(len(matrix)):
    for j in range(len(matrix)):
        new_i = circular_subtraction(i)
        new_matrix[j][new_i] = matrix[i][j]
        print("New element added from {},{} to {},{} ::: {} to {}".format(i+1,j+1,j+1,new_i+1,matrix[i][j],new_matrix[j][new_i]))

for each_row in new_matrix:
    print(each_row)




matrix = [[1,2,3],[4,5,6],[7,8,9]]
print("Length of the matrix : ",len(matrix))
for each_row in matrix:
    print(each_row)
print()
matrix = rotate_clock(matrix)

the input matrix was

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

The expected result was:

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

Result is:

[7, 4, 1]
[2, 5, 2]
[1, 2, 1]

Upvotes: 4

Views: 10504

Answers (7)

Devashish Somani
Devashish Somani

Reputation: 1

Generally all solution are for square matrix, Below one will for any matrix:

mat = [[1, 2, 3, 5],
     [5, 6, 7, 1],
     [9, 10, 11, 8],
     [4, 7, 4, 3]]
 
def rotate_matrix(a):
    b = []
    i = len(a)-1
    while i>=0:
        if len(a) == len(a[-1]):
            for j in range(0, len(a)):
                print(j)
                if (len(b) < (j+1)):
                    b.append([a[i][j]])
                    print(b)
                else:
                    b[j].append(a[i][j])
                    print(b)
            i -= 1
        else:
            for j in range(0, len(a)+1):
                print(j)
                if (len(b) < (j+1)):
                    b.append([a[i][j]])
                    print(b)
                else:
                    b[j].append(a[i][j])
                    print(b)
            i -= 1
    return b
    
print(rotate_matrix(mat))

Upvotes: 0

Drisya Dinesh
Drisya Dinesh

Reputation: 1

A simple solution to rotate any matrix would be

import copy
def rotateImage(a):
 out = copy.deepcopy(a)
 x = 0;
 y = 0;
 for i in a:
  l = len(i)
  for j in i:
   out[y][x+l-1] = j
   y += 1
   if(y == l):
    y=0
  x -= 1
 return(out)

Upvotes: 0

Rashida
Rashida

Reputation: 491

In very simple python, this code works:

def rotate_matrix(a):
    b = []
    i = len(a)-1
    while i>=0:
        for j in range(0, len(a)):
            if (len(b) < (j+1)):
                b.append([a[i][j]])
            else:
                b[j].append(a[i][j])
        i -= 1
    return b

I printed b. That looked like this: [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

Upvotes: 2

Oleg
Oleg

Reputation: 620

You can use the numpy rot90 function for this: np.rot90

mat = [[1, 2, 3], [4,5,6,], [7,8,9]]
np.rot90(mat, k=1, axes=(1,0))

k - indicates number of rotations
axes - indicates the direction of rotation

Output

array([[7, 4, 1],
   [8, 5, 2],
   [9, 6, 3]])

The issue in your code

The code is missing indents (but assuming they are correct)
the line :

new_matrix = matrix

assigns a new reference to the matrix variable.
In python the default isn't copy by value. You can use deep copy function : copy.deepcopy(x[, memo])

import copy

def rotate_clock(matrix):
    new_matrix = copy.deepcopy(matrix)

OR

def rotate_clock(matrix):
    new_matrix = [row[:] for row in matrix]

Otherwise, each change you make to new_matrix is being done in the original matrix as well. (since new_matrix is just a reference to matrix)

Upvotes: 5

cph_sto
cph_sto

Reputation: 7585

A general method to rotate the Matrix, irrespective of shape.

import numpy as np
A=np.array([[1, 2, 3, 33], [4, 5, 6, 66], [7, 8, 9, 99]])
A
array([[ 1,  2,  3, 33],
       [ 4,  5,  6, 66],
       [ 7,  8,  9, 99]])

rotated_A=np.zeros((len(A[0]),len(A)))
for i in range(len(A)):
    for j in range(len(A[0])):
        rotated_A[j][len(A)-1-i]=A[i][j]
rotated_A
array([[  7.,   4.,   1.],
       [  8.,   5.,   2.],
       [  9.,   6.,   3.],
       [ 99.,  66.,  33.]])

Upvotes: 1

b-fg
b-fg

Reputation: 4137

numpy.rot90 could come handy as well:

import numpy as np

a = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]
a_rot = np.rot90(a, k=3).tolist()
for row in a_rot:
  print(row)

Output

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

Upvotes: 1

Dani Mesejo
Dani Mesejo

Reputation: 61900

You could do something like this:

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

rotated = [list(reversed(col)) for col in zip(*matrix)]

for row in rotated:
    print(*row)

Output

7 4 1
8 5 2
9 6 3

The for col in zip(*matrix) gets the column of the matrix, once you have the columns you need to reverse them using list(reversed(col)), then use a list comprehension to put all together:

rotated = [list(reversed(col)) for col in zip(*matrix)]

The above list comprehension is equivalent to the following less pythonic for loop:

rotated = []
for col in zip(*matrix):
    rotated.append(list(reversed(col)))

Further

  1. Documentation on zip, reversed and list.
  2. The notation *matrix is known as tuple unpacking, more here.

Upvotes: 10

Related Questions