Reputation: 632
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
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
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
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