1

I'm trying to 'rotate' a grid 90 degrees clockwise and came up with the following Python code.

def rotate90(grid):
    rotatedGrid = grid[:]
    for i in range (0, len(grid)):
        for j in range (0, len(grid)):
            rotatedGrid[i][j] = grid[-(j+1)][i][:]
    return rotatedGrid

printing rotate90(grid) on the grid [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']] outputs [['7', '4', '7'], ['8', '5', '4'], ['9', '4', '7']], whereas I expected [['7', '4', '1'], ['8', '5', '2'], ['9', '6', '3']]. What is the reason for this difference?

(The reason I haven't converted these to ints is that eventually I will be using '@' and '-' characters rather than numbers.)

HelloWorld4444
  • 125
  • 1
  • 9
  • I'm sorry if there's some duplication, but what seems like the critical line of my code looks almost identical to that of the first solution, yet mine doesn't seem to work. (The grid will be small, so an O(n^2) algorithm is fine.) – HelloWorld4444 Jan 05 '18 at 15:50
  • 1
    [Python solution](https://stackoverflow.com/a/496056/7851470) – Georgy Jan 05 '18 at 15:55
  • I'm sorry I missed that. I'll search harder next time before asking. The answer I've accepted might add something new though (I'm sure it's elsewhere, but perhaps not on the copy threads). – HelloWorld4444 Jan 05 '18 at 15:56

2 Answers2

4

Your function doesn't work because you didn't make a new structure when you initialized rotatedGrid. You made a copy of each row, but the elements are pointers to the originals in grid. When you assigned within the loop, you were pointing to shared matrix locations.

Fix it with this:

from copy import deepcopy

def rotate90(grid):
    rotatedGrid = deepcopy(grid)

Given that change, your code produces the desired output.

Prune
  • 76,765
  • 14
  • 60
  • 81
  • Thank you for explaining. I thought that the `[:]` made a copy. Why doesn't that work in this case? – HelloWorld4444 Jan 05 '18 at 15:55
  • 1
    @PeterW `[:]` do make a copy of list, but `=` assign reference from source to target. Check [this](https://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-deepcopy-and-normal-assignm) question to understand the difference in more details. – Sohaib Farooqi Jan 05 '18 at 15:59
  • `[:]` is a shallow copy. There's a pretty good explanation in the [documentation of the `copy` module](https://docs.python.org/3/library/copy.html) – Patrick Haugh Jan 05 '18 at 16:00
2

We can easily transpose a list l with zip(*l), then reverse the sublists

def rot_90(l):
    return [list(reversed(x)) for x in zip(*l)]

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

returns

[['7', '4', '1'], ['8', '5', '2'], ['9', '6', '3']]
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • That's great to know. I hadn't come across 'zip' before, as I'm still fairly new to Python. Out of curiosity, do you know why my function didn't work? – HelloWorld4444 Jan 05 '18 at 15:52
  • 1
    `zip` is super useful. When you have a minute you should go over the documentation for it: https://docs.python.org/3/library/functions.html#zip – Patrick Haugh Jan 05 '18 at 16:01
  • Yes, I definitely should. (Particularly as I'm about to enter an informatics olympiad for fun, and so shouldn't be fumbling around unnecessarily!) – HelloWorld4444 Jan 05 '18 at 16:23