user2298943
user2298943

Reputation: 632

Creating a shifted matrix

I am trying to generate a matrix that shifts the values in a diagonal way, I am not familiar with mathematic jargon, but this must be something quite default.

My attempts gave me:

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

I want (notice the further away from the starting point, the higher the value, mind the diagonal shift aswell)

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

I have tried to use collections.deque for this purpose but it seems not the way to go

Upvotes: 1

Views: 354

Answers (3)

A.P.
A.P.

Reputation: 1159

Here's a one-liner that generates your second matrix:

[[(3*i + j, abs(i-j) + min(i,j)) for j in range(3)] for i in range(3)]

Which generates:

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

Upvotes: 1

theodox
theodox

Reputation: 12218

The problem is much easier if you treat this as two matrices overlaid instead of a single matrix of tuples:

m1 = [ [0,1,2], [3,4,5], [6,7,8]]
m2 = [ [0,1,2], [0,1,2], [0,1,2]]

def shift (row, pivot):
    for idx, item in enumerate(row):
        if idx <= pivot:
            yield pivot
        else:
            yield item

def merge (mat1, mat2):
    result = []
    for r1, r2 in zip (mat1, mat2):
        new_row = [(c1, c2) for c1, c2 in zip ( r1, r2)]
        result.append(new_row)
    return result

shifted =[]
for idx, row in enumerate(m2):
    shifted[idx] = [i for i in shift(row, idx)]

print merge (m1, shifted)
#[[(0, 0), (1, 1), (2, 2)], [(3, 1), (4, 1), (5, 2)], [(6, 2), (7, 2), (8, 2)]]

It's a bit trickier if you have to support different shift patterns but you could pass in the test as a lambda in the shift function

Upvotes: 1

asdf
asdf

Reputation: 3067

You'll need to write a couple loops to handle the shifting and open a new matrix to accept the shift (since tuples are immutable).

matrix = [[(0, 0), (1, 1), (2, 2)], [(3, 0), (4, 1), (5, 2)], [(6, 0), (7, 1), (8, 2)]]

shifted_matrix = [[] for _ in range(len(matrix))]
for i in xrange(len(matrix)):
    for j in xrange(len(matrix[i])):
        if i-j >= 0:
            shifted_matrix[i].append((matrix[i][j][0], matrix[i][j][1] + i-j))
        else:
            shifted_matrix[i].append((matrix[i][j][0], matrix[i][j][1]))

I don't know exactly what you mean by a 'start' matrix, but I'm assuming you want a function you can call on any matrix? Here's the same code reformatted to accept a matrix as an argument and return a shifted matrix.

def diagonalize_matrix(matrix):
    shifted_matrix = [[] for _ in range(len(matrix))]
    for i in xrange(len(matrix)):
        for j in xrange(len(matrix[i])):
            if i-j >= 0:
                shifted_matrix[i].append((matrix[i][j][0], matrix[i][j][1] + i-j))
            else:
                shifted_matrix[i].append((matrix[i][j][0], matrix[i][j][1]))
    return shifted_matrix

Then, you can call this from the command line or wherever you're using it by saying

diagonalize_matrix(matrix)

You could also reformat it to accept another variable defining the type of diagonalization (if it should increase from top-left, top-right, bottom-left, bottom-right), but I'm not sure I fully understand what you're asking for?

Upvotes: 3

Related Questions