• + 1 comment

    One of the idea is by extracting to straps, rotate it, and combine it back as a matrix.

    For the last one, combining it back is quite tedious, so I personally prefer to utilize classes (in-place assignments / reference-assignment) so that I dont need to deal the last one (combine it back)

    For the strap example, it should be: matrix (height=5, width=4):

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

    There will be 2 straps: [1, 5, 9, 13, 17, 18, 19, 20, 16, 12, 8, 4, 3, 2] and the second one: [6, 10, 14, 15, 11, 7, ]

    class Value():
        def __init__(self, val):
            self.val = val
        
        def set(self, new_val):
            self.val = new_val
            
        def __str__(self):
            return str(f"{self.val}")
    
        def __repr__(self):
            return str(f"{self.val:2d}")
    
    
    def matrixRotation(matrix, r):
        h = len(matrix)
        w = len(matrix[0])
        
        matrix = [   # convert to reference-based values
            [
                Value(col)
                for col in row
            ]
            for row in matrix
        ]
        # max number of straps. indexes means strap
        num_of_indexes = min(h,w) // 2  
    
        for index in range(num_of_indexes):
            extracted = extract(matrix, index)
            extracted_render = [x.val for x in extracted]
            r_mod = r % len(extracted_render)
            for i in range(len(extracted)):
                extracted[i].val = extracted_render[i-r_mod]
    						
    		# combine back process. But because we use classes/references, 
    		# dont need to do extra complex things here. Just print as usual
        for row in matrix:
            print(" ".join(map(str, row)))
            
        
    
    def extract(matrix, dia_index):  # extract strap arrays by strap-index 
        h = len(matrix)
        w = len(matrix[0])
        ret = []
        for y in range(dia_index+0, h-dia_index):  # from top-left to bottom
            ret.append(matrix[y][dia_index])
        for x in range(dia_index+1, w-dia_index):  # from bottom-left to right (except the first item, already included by for-loop above)
            ret.append(matrix[-dia_index-1][x])
        for y in range(h-1 - 1 - dia_index, dia_index - 1, -1):  # from bottom-right to top (except the first item)
            ret.append(matrix[y][-dia_index-1])
        for x in range(w-1 - 1 - dia_index, dia_index, -1):  # from top-right to left   (except first and last item)
            ret.append(matrix[dia_index][x])
        return ret