Skip to content

Commit a66b6ad

Browse files
committed
implement rotate mat in place, add more test cases
1 parent fba8e45 commit a66b6ad

File tree

1 file changed

+97
-10
lines changed

1 file changed

+97
-10
lines changed

Python/chapter01/1.7 - Rotate Matrix/miguel_1.7_sol.py

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
the image by 90 degrees. Can you do this in place?
66
"""
77
import unittest
8-
from typing import List, Callable
8+
from typing import List
99

1010

1111
def rotate_matrix(matrix: List[List[int]], N: int) -> List[List[int]]:
@@ -24,19 +24,45 @@ def rotate_matrix(matrix: List[List[int]], N: int) -> List[List[int]]:
2424
return rotated
2525

2626

27-
def rotate_matrix_in_place(matrix: List[List[int]], N: int) -> List[List[int]]:
27+
def rotate_matrix_in_place(matrix: List[List[int]], start_row: int, start_col: int, N: int) -> List[List[int]]:
2828
"""
2929
Does the same as rotate_matrix, but in place.
30+
Runtime: O(N^2), asymptotic runtime depends on N. We make N^2 swaps.
31+
Space Complexity: O(1), constant amount of temp variables that does not depend on N.
32+
Note: I am assuming that compiler will optimize the tail recursion.
3033
:param matrix: an NxN matrix
34+
:param start_row: starting row index
35+
:param start_col: starting col index
3136
:param N: the size of the matrix (NxN)
32-
:return:
37+
:return: the input matrix, but rotated
3338
"""
34-
return matrix
39+
num_rotations = 4
40+
if N == 0 or N == 1:
41+
return matrix
42+
col = start_col
43+
while True:
44+
rotated_row = start_row
45+
rotated_col = col
46+
temp_new = matrix[start_row][col]
47+
for r in range(0, num_rotations):
48+
temp = temp_new
49+
# compute new rotated indices
50+
prev_col = rotated_col
51+
rotated_col = N - 1 - rotated_row + (start_row * 2) # offset to account for reduced N
52+
rotated_row = prev_col
53+
# store value at newly computed indices
54+
temp_new = matrix[rotated_row][rotated_col]
55+
matrix[rotated_row][rotated_col] = temp
56+
if col - start_col >= N - 2:
57+
break
58+
col = col + 1
59+
return rotate_matrix_in_place(matrix, start_row + 1, start_col + 1, N - 2)
3560

3661

3762
class TestRotateMatrixFunction(unittest.TestCase):
38-
def _run_tests(self, f: Callable[[List[List[int]], int], List[List[int]]]):
39-
cases = [
63+
64+
def setUp(self):
65+
self.cases = [
4066
(
4167
[
4268
[1, 2, 3, 4],
@@ -73,14 +99,75 @@ def _run_tests(self, f: Callable[[List[List[int]], int], List[List[int]]]):
7399
[
74100
[1]
75101
]
102+
),
103+
(
104+
[
105+
[1, 2, 3, 4, 5, 6],
106+
[7, 8, 9, 10, 11, 12],
107+
[13, 14, 15, 16, 17, 18],
108+
[19, 20, 21, 22, 23, 24],
109+
[25, 26, 27, 28, 29, 30],
110+
[31, 32, 33, 34, 35, 36]
111+
],
112+
6,
113+
[
114+
[31, 25, 19, 13, 7, 1],
115+
[32, 26, 20, 14, 8, 2],
116+
[33, 27, 21, 15, 9, 3],
117+
[34, 28, 22, 16, 10, 4],
118+
[35, 29, 23, 17, 11, 5],
119+
[36, 30, 24, 18, 12, 6]
120+
]
121+
),
122+
(
123+
[
124+
[1, 2, 3, 4, 5],
125+
[6, 7, 8, 9, 10],
126+
[11, 12, 13, 14, 15],
127+
[16, 17, 18, 19, 20],
128+
[21, 22, 23, 24, 25]
129+
],
130+
5,
131+
[
132+
[21, 16, 11, 6, 1],
133+
[22, 17, 12, 7, 2],
134+
[23, 18, 13, 8, 3],
135+
[24, 19, 14, 9, 4],
136+
[25, 20, 15, 10, 5]
137+
]
138+
),
139+
(
140+
[
141+
[1, 2, 3, 4, 5, 6, 7],
142+
[8, 9, 10, 11, 12, 13, 14],
143+
[15, 16, 17, 18, 19, 20, 21],
144+
[22, 23, 24, 25, 26, 27, 28],
145+
[29, 30, 31, 32, 33, 34, 35],
146+
[36, 37, 38, 39, 40, 41, 42],
147+
[43, 44, 45, 46, 47, 48, 49]
148+
],
149+
7,
150+
[
151+
[43, 36, 29, 22, 15, 8, 1],
152+
[44, 37, 30, 23, 16, 9, 2],
153+
[45, 38, 31, 24, 17, 10, 3],
154+
[46, 39, 32, 25, 18, 11, 4],
155+
[47, 40, 33, 26, 19, 12, 5],
156+
[48, 41, 34, 27, 20, 13, 6],
157+
[49, 42, 35, 28, 21, 14, 7]
158+
]
76159
)
77160
]
78-
for matrix, N, expected in cases:
79-
self.assertEqual(f(matrix, N), expected, msg=(matrix, N, expected))
80161

81162
def test_rotate_matrix(self):
82-
self._run_tests(rotate_matrix)
83-
# self._run_tests(rotate_matrix_in_place)
163+
for matrix, N, expected in self.cases:
164+
self.assertEqual(rotate_matrix(matrix, N), expected, msg=(matrix, N, expected))
165+
166+
def test_rotate_matrix_in_place(self):
167+
start_row = 0
168+
start_col = 0
169+
for matrix, N, expected in self.cases:
170+
self.assertEqual(rotate_matrix_in_place(matrix, start_row, start_col, N), expected, msg=(matrix, N, expected))
84171

85172

86173
if __name__ == '__main__':

0 commit comments

Comments
 (0)