In a bigger program I made I need to be able to generate a grid with n rows and m columns. After that I need a function that will let me rotate this grid and with it rotate the values of the original grid.

This is the code that let's me generate a grid:

class Grid(object):
    def __init__(self, width, height):
        self.grid = []
        self.width = width
        self.height = height
        self.length = width * height
        for x in range(self.width):
            col = []
            for y in range(self.height):
                col.append(Cell(x, y, self.grid))
            self.grid.append(col)

    def __getitem__(self, (x, y)):
        return self.grid[x][y]
        
    def printGrid(self):
        for y in range(len(self.grid[0])):
            for x in range(len(self.grid)):
                print self.grid[x][y].value,
            print

class Cell(object):
    def __init__(self, x, y, grid):
        self.x = x
        self.y = y
        self.grid = grid
        self.value = 0
        self.clusterId = -1

my_grid = Grid(5, 3)
my_grid[0, 0].value = 1
my_grid[4, 0].value = 2
my_grid[0, 2].value = 3
my_grid[4, 2].value = 4
my_grid.printGrid()

It outputs the following:

1 0 0 0 2
0 0 0 0 0
3 0 0 0 4

Say we take the following notation of cell locations:

A B C D E
---------------
0| 1 0 0 0 2
1| 0 0 0 0 0
2| 3 0 0 0 4

I want to rotate the grid so it becomes:

0 1 2
---------------
A| 3 0 1
B| 0 0 0
C| 0 0 0
D| 0 0 0
E| 4 0 2

I tried to notate what happened per cell in the following table:

SOURCE | ROTATED
A0 1 | 3
A1 0 | 0
A2 3 | 1
B0 0 | 0
B1 0 | 0
B2 0 | 0
C0 0 | 0
C1 0 | 0
C2 0 | 0
D0 0 | 0
D1 0 | 0
D2 0 | 0
E0 2 | 4
E1 0 | 0
E2 4 | 2

I've tried in a rotate function to take the original grid's width and height, and from that instantiate a destination grid by

def rotate(self, n):
        source = self
        width = (source.width)
        height = (source.height)
        n %= 4
        if n == 0:
            pass
        if n == 1:
            destination = Grid(height, width)
            for x in range(destination.height):
                for y in range(destination.width):
                    #???                    
            destination.printGrid()

Where n == 1 stands for rotating 1 time by 90 degrees. How should I code my for loop to do the proper rotation?

I've tried it earlier with thanks to Gribouillis's code:

def rotated(self, n):
        L = self.toList()
        n %=4 
        if n ==0 :
            pass 
        elif n ==1 :
            L =[list (x )for x in zip (*reversed (L))]
        elif n ==2 :
            L =[list (reversed (x ))for x in reversed (L)]
        else :
            L =[list (x )for x in reversed (zip (*L))]
        return Grid.fromList(L)

    def toList(self):
        return [tuple(cell.value for cell in row) for row in self.grid]

    @staticmethod
    def fromList(L):
        height, width = len(L), len(L[0])
        self = Grid(width, height)
        for x in range(height):
            for y in range(width):
                 self[(x,y)].value = L[x][y]
        return self

Unfortunately this let's me only rotate square grids and after talking to my teacher he said the rotate function should be more simple, with for loops like I try to do now. Despite I'm trying to logically think what sould happen in this for loop I haven't found out till now.

Can someone point out what I should do in the new rotate method so it can properly rotate square AND rectangular grids (with different width and height)?

Thanks in advance for helping me out here :)

Pfeeeew :)

I reworked on my loop and wrote everything out to finally come to the solution (i hope :P):

Print x, y for destination grid:

def rotate(self, n):
        source = self
        width = (source.width)
        height = (source.height)
        n %= 4
        if n == 0:
            pass
        if n == 1:
            destination = Grid(height, width)
            print destination.width
            print destination.height
            print ('-'*20)
            for x in range(destination.width):
                for y in range(destination.height):
                    print x, y
1 0 0 0 2
0 0 0 0 0 
3 0 0 0 0

should become:

3 0 1
0 0 0
0 0 0 
0 0 0
4 0 2
x, y      destination value:  describing in source[...,...].value notation:
0, 0     3                             source[0, 2].value
0, 1     0                             source[1, 2].value 
0, 2     0                             source[2, 2].value
0, 3     0                             source[3, 2].value
0, 4     4                             source[4, 2].value
1, 0     0                             source[0, 1].value
1, 1     0                             source[1, 1].value
1, 2     0                             source[2, 1].value
1, 3     0                             source[3, 1].value
1, 4     0                             source[4, 1].value
2, 0     1                             source[0, 0].value
2, 1     0                             source[1, 0].value
2, 2     0                             source[2, 0].value
2, 3     0                             source[3, 0].value
2, 4     2                             source[4, 0].value

Then I could transform this description of source[...,...].value to something i could use in the for loop.
The first part was source[y, ...].value, and after some looking I found that the second part was equal to destination.width-1-x what's giving me:

destination[x, y].value = source[y, destination.width-1-x].value

class Grid(object):
    def __init__(self, width, height):
        self.grid = []
        self.width = width
        self.height = height
        self.length = width * height
        for x in range(self.width):
            col = []
            for y in range(self.height):
                col.append(Cell(x, y, self.grid))
            self.grid.append(col)

    def __getitem__(self, (x, y)):
        return self.grid[x][y]

    def rotate(self, n):
        source = self
        width = (source.width)
        height = (source.height)
        n %= 4
        if n == 0:
            pass
        if n == 1:
            destination = Grid(height, width)
            for x in range(destination.width):
                for y in range(destination.height):
                    destination[x, y].value = source[y, destination.width-1-x].value
            destination.printGrid()
            
    def printGrid(self):
        for y in range(len(self.grid[0])):
            for x in range(len(self.grid)):
                print self.grid[x][y].value,
            print

class Cell(object):
    def __init__(self, x, y, grid):
        self.x = x
        self.y = y
        self.grid = grid
        self.value = 0
        self.clusterId = -1

my_grid = Grid(5, 3)
my_grid[0, 0].value = 1
my_grid[4, 0].value = 2
my_grid[0, 2].value = 3
my_grid[4, 2].value = 4
my_grid.printGrid()
print ('-'*20)
my_grid.rotate(1)
OUTPUT:
1 0 0 0 2
0 0 0 0 0
3 0 0 0 4
--------------------
3 0 1
0 0 0
0 0 0
0 0 0
4 0 2

So it seems to work now, allthough I don't know if anyone has more ideas on this to improve or if I'm doing something wrong still? Let me know please :)
Sorry for the long explanation, I guess I was just happy to find the solution with some good old logic thinking (something which I suck at most of the times I guess :P)

commented: congratulations! +2
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.