I have a code snippet that creates a matrix by populating the upper elements one by one and populate the lower elements afterwards (if the upper element is x
then the lower is 1/x
)
n = 4
m = np.ones([n, n])
for i in range(0,n):
for j in range(0,n):
if i < j:
x = input()
m[i, j] = float(x)
m[j, i] = 1 / float(x)
In the second code I can populate the matrix at once, but I need to populate the elements row-wise from top left to bottom right
n = int(input())
entries = list(map(int, input().split()))
matrix = np.array(entries).reshape(n, n)
My question is: is there any way can I populate the upper triangle of the matrix first like the first snippet, but only by entering a list once like the second snippet?
Ex.
n = 3
Input = 2 3 4 (list)
Expected output=
[[1. 2. 3. ]
[0.5 1. 4. ]
[0.33333333 0.25 1. ]]
CodePudding user response:
np.triu_indices
and np.tril_indices
are your friends here. These functions supply the indices of the upper or lower triangle of a matrix. You can use the indices to assign your flat list into the portion of the matrix you want:
n = int(input())
entries = np.array(list(map(int, input().split())))
matrix = np.ones((n, n))
matrix[np.triu_indices(n, 1)] = entries
matrix[np.tril_indices(n, -1)] = 1 / entries
Since your matrices are square, supplying both n
and the list is redundant because the length of the list must be a triangular number. len(entries) = (n**2 - n) / 2
, only has a valid integer solution when 1 8 * len(entries)
is an odd perfect square:
entries = np.array(list(map(int, input().split())))
d = np.sqrt(1 8 * entries.size)
if np.round(d) != d or d % 2:
raise ValueError('invalid number of entries')
n = (d 1) // 2