0

I have a list as follows:

[[1],[2,1],[3,2,1],[3,1,2],[1,2],[1]]

The above is the input.

These are the diagonal elements of the orignal list:

[[3,3,1,1],[2,2,1,2],[1,1,1,2]]

That is,

3 3 1 1
2 2 1 2
1 1 1 2

So the question is to reconstruct the original list from the inputs which are diagonal elements.

As you can see, the diagonal elements are following the direction of the main diagonal. How to achieve this for a matrix of any arbitrary dimensions?

  • Does this answer your question? [Shear a numpy array](https://stackoverflow.com/questions/4998587/shear-a-numpy-array) – norok2 Apr 14 '20 at 08:53
  • You need to first zero-pad your list and then create a matrix, and apply one of the shear methods from the proposed duplicate. – norok2 Apr 14 '20 at 08:56
  • I will see it @norok2. Thanks. –  Apr 14 '20 at 19:52

1 Answers1

0

You can do this with the following steps:

  • fill a zero-background matrix from the input (so that the values of interest are sheared)
  • apply a shearing (and evenutally a transposition) so that all the zeros end up in some rows/columns at the edge
  • slice out the background zeros

This can be done either with NumPy arrays or with plain Python lists.

With NumPy

import numpy as np


l = [[1],[2,1],[3,2,1],[3,1,2],[1,2],[1]]
m = np.array([[3,3,1,1],[2,2,1,2],[1,1,1,2]])

rows = max(len(x) for x in l)
cols = len(l) - rows + 1

# fill a shear matrix from the input
a = np.zeros((rows, len(l)), dtype=m.dtype)
for j, x in enumerate(l):
    k = rows - j - 1
    a[:, j] = [0] * k + x + [0] * (-k - 1)
print(a)
# [[0 0 3 3 1 1]
#  [0 2 2 1 2 0]
#  [1 1 1 2 0 0]]

# apply the shearing
for i in range(rows):
    a[i, :] = np.roll(a[i, :], i)
print(a)
# [[0 0 3 3 1 1]
#  [0 0 2 2 1 2]
#  [0 0 1 1 1 2]]

# slice out the zeros
a = a[:, len(l) - cols:]
print(a)
# [[3 3 1 1]
#  [2 2 1 2]
#  [1 1 1 2]]

np.all(a == m)
# True

With lists

def transpose(seq):
    return type(seq)(map(type(seq), zip(*seq)))


def rotate(seq, i):
    return seq[-i:] + seq[:-i]


def shear(seq):
    return type(seq)(rotate(x, i) for i, x in enumerate(seq))


l = [[1],[2,1],[3,2,1],[3,1,2],[1,2],[1]]
m = [[3,3,1,1],[2,2,1,2],[1,1,1,2]]

rows = max(len(x) for x in l)
cols = len(l) - rows + 1

# fill zero-background matrix from the input
a = [([0] * (rows - j - 1) + x + [0] * (j - rows)) for j, x in enumerate(l)]
print(a)
# [[0, 0, 1], [0, 2, 1], [3, 2, 1], [3, 1, 2], [1, 2, 0], [1, 0, 0]]

# apply the transposition and the shearing
print(transpose(a))
# [[0, 0, 3, 3, 1, 1], [0, 2, 2, 1, 2, 0], [1, 1, 1, 2, 0, 0]]
print(shear(transpose(a)))
# [[0, 0, 3, 3, 1, 1], [0, 0, 2, 2, 1, 2], [0, 0, 1, 1, 1, 2]]

# slice out the zeros
a = [x[len(a) - cols:] for x in shear(transpose(a))]
print(a)
# [[3, 3, 1, 1], [2, 2, 1, 2], [1, 1, 1, 2]]
print(a == m)
# True

or, without separating the logical operations to be more concise:

l = [[1],[2,1],[3,2,1],[3,1,2],[1,2],[1]]
m = [[3,3,1,1],[2,2,1,2],[1,1,1,2]]

rows = max(len(x) for x in l)
cols = len(l) - rows + 1

a = [([0] * (rows - j - 1) + x + [0] * (j - rows)) for j, x in enumerate(l)]
a = [list(x[len(a) - cols - i:len(a) - i]) for i, x in enumerate(zip(*a))]
print(a)
# [[3, 3, 1, 1], [2, 2, 1, 2], [1, 1, 1, 2]]
print(a == m)
# True
norok2
  • 25,683
  • 4
  • 73
  • 99