Transposing a list of lists in python - python

Why does this code doesn't transpose the list of list
import sys
t = input()
for k in range(t):
n,m = [int(i) for i in raw_input().strip().split()]
A = [[None]*m]*n
B = [[None]*n]*m
for l in range(n):
A[l] = raw_input().strip().split()
for j in range(m):
for i in range(n):
B[j][i] = A[i][j]
print B
I know there are better methods to transpose a matrix but why does this doesn't work?

Replace
A = [[None]*m]*n
B = [[None]*n]*m
with
A = [[None for x in range(m)] for x in range(n)]
B = [[None for x in range(n)] for x in range(m)]
Why?
>>> l = [2]*5
>>> l
[2,2,2,2,2]
>>> [id(value) for value in l]
[26089400, 26089400, 26089400, 26089400, 26089400]
Can you see what happened there?
There's just one copy in memory holding a value '2'. All list elements are pointing to that same memory location holding the value '2'.
So, when you do:
A = [[None]*m]*n
you are creating a 2d array with elements pointing to the same memory location. Changing one of them, changes the value stored at that common memory location, hence changes value stored by all the elements!
That is why the program didn't work.
Read more about how all this works in Python, in detail, here:
http://foobarnbaz.com/2012/07/08/understanding-python-variables/

Related

Can't figure out why I keep getting a "list index out of range" error. Can someone assist me?

I keep getting a "list index out of range" error, but don't know why. Can someone help?
arr = []
if __name__ == '__main__':
x = int(input())
y = int(input())
z = int(input())
n = int(input())
for x in range (x+1):
for y in range(y+1):
for z in range(z+1):
arr.append([x,y,z])
for i in range(len(arr)):
if (arr[i][0] + arr[i][1] + arr[i][2] == n):
del arr[i]
print(arr)
This is happening because you're mutating your list as you traverse through it. In your specific example, you would actually be better off creating a new list from the old list. In this example:
arr = [x for x in arr if (x[0] + x[1] + x[2] != n)]
EDIT: In addition to the comment about the scope of this activity relative to main.
It's better to build a list like this as a comprehension, where you can filter the elements as you build the list rather than having to go back and try to extract them after the fact:
x, y, z, n = (int(input()) for _ in range(4))
arr = [
[i, j, k]
for i in range(x+1)
for j in range(y+1)
for k in range(z+1)
if i + j + k != n
]
That is because you iterate over the len of an array, but that len is computed and stored at the beginning, it isn't update. Let's say the array if of len 5, the loop generates 0,1,2,3,4 but if you delete an item during the loop, when doing arr[4] it'll fail
The best solution is to keep interesting items, not delete the others, whether with another array, or a list comprehension. Also you can iterate of the values of an array, not on indices
# new array
new_vals = []
for v in arr:
if sum(v) != n:
new_vals.append(v)
# list comprehension
arr = [v for v in arr if sum(v) != n]

python inverse matrix without numpy

I can't figure it out what's wrong with my code, it's rly frustrating.
I have to make inverse matrix function, what I thought I've done. I don't know why it doesn't work. The problem is probably in line with stars, after this step my matrix named mat is changed to identity matrix, but why? Before stars it prints my mat matrix normaly which I gave to function, but after stars it's a identity matrix, I don't understand why it happend. Here's what I have:
def identity_matrix_convertion(m):
x = m[:]
for i in range(len(x)):
for j in range(len(x[0])):
if i == j:
x[i][j] = 1
else:
x[i][j] = 0
return x
def inverse_matrix(mat):
n = len(mat)
am = mat[:]
show_matrix(mat)
**i = identity_matrix_convertion(am)**
show_matrix(mat)
im = i[:]
ind = list(range(n))
print(len(mat))
if determinant(mat) == 0:
print("This matrix doesn't have an inverse.")
if len(mat) == len(mat[0]):
for i in range(n):
scal = 1.0 / am[i][i]
for j in range(n):
am[i][j] *= scal
im[i][j] *= scal
for k in ind[0:i] + ind[i + 1:]:
current_scal = am[k][i]
for l in range(n):
am[k][l] = am[k][l] - current_scal * am[i][j]
im[k][l] = im[k][l] - current_scal * im[i][j]
return im
so after line **i = identity_matrix_convertion(am)** my mat matrix is changed into identity matrix, but why?
The result is:
1.0 2.0 3.0
2.0 1.0 3.0
4.0 3.0 2.0
The result is:
1 0 0
0 1 0
0 0 1
Instead of saying x = m[:] in the identity_matrix_convertion() function, you should add the following snippet:
x = []
for i in m:
arr = [a for a in i]
x.append(arr)
x = m[:] is still referencing m instead of just making a copy.
Following up on #NumberC's answer, the x = m[:] does make a copy, but only a shallow copy. The copied list will contain references to internal lists of the other list, and so manipulating those lists within x cause change in m too. This is because we represent the 2D matrix as list of lists. If someone would reorder the lists in m (so not the items within the lists but just the pure order of the lists within m) the order would stay the same in the x copy. However any change within the list of the lists is mutating the other too. I hope this is not confusing, List changes unexpectedly after assignment. Why is this and how can I prevent it? has some figures.
Since we don't have to scare away from [:] we can still say:
x = new_list = [y[:] for y in m]
Or even better: we can use the built-in copy module (available everywhere):
import copy
x = copy.deepcopy(m)
See also: Copying nested lists in Python

I want to create array problem using python

You all have seen how to write loops in python. Now is the time to implement what you have learned.
Given an array A of N numbers, you have to write a program which prints the sum of the elements of array A with the corresponding elements of the reverse of array A.
If array A has elements [1,2,3], then reverse of the array A will be [3,2,1] and the resultant array should be [4,4,4].
Input Format:
The first line of the input contains a number N representing the number of elements in array A.
The second line of the input contains N numbers separated by a space. (after the last elements, there is no space)
Output Format:
Print the resultant array elements separated by a space. (no space after the last element)
Example:
Input:
4
2 5 3 1
Output:
3883
Explanation:
Here array A is [2,5,3,1] os reverse of this array is [1,3,5,2] and hence the resultant array is [3,8,8,3]
My solution is not working.
my solution is:
r=input()
r=int(r)
result_t = []
d=[]
for i in range(0, r):
c=input()
c=int(c)
t = i
result_t.append(c)
d=reversed(result_t)
d=int(d)
s=result_t+d
for i in range(0, r):
print(s[i])
You just need to loop over both result_t and d. You can use zip() to combine two lists so you can loop over them in parallel:
r=input()
r=int(r)
result_t = []
for i in range(r):
c=input()
c=int(c)
result_t.append(c)
d = reversed(result_t)
result = [x + y for x, y in zip(result_t, d)]
print(result.join(" "))
You can also do it without making the reversed list.
result = [x + result_t[-(i+1)] for i, x in enumerate(result_t)]
When you use a negative index in a list, it counts from the end. You have to add 1 before negating, because the last element is -1 (since -0 is the same as 0, which is the first element).
"can only concatenate list (not "list_reverseiterator") to list"
reversed(result_t) returns not the list but iterator
try:
rev = []
for i in reversed(result_t):
rev.append(i)
print(rev)
Try This One:
x = input()
result_t = [int(x) for x in input().split()]
rev = [x for x in reversed(result_t)]
result = [int(x) + int(y) for x, y in zip(result_t, rev)]
for i in result:
print(i,end=" ")
Here array A is [2,5,3,1] and reverse of this array is [1,3,5,2] and hence the resultant array is [3,8,8,3].
a = []
n = int(input("Enter the number of elements"))
for i in range(n):
x = int(input("Enter the elements"))
a.append(x)
print(a)
res = []
b = [None] * len(a)
for i in range(0, len(a)):
b[i] = a[i]
b.reverse()
print(b)
for i in range(0, len(a)):
res.append(a[i] + b[i])
print(res)

Create a loop for a set of similar statements in python

I have a 2D matrix called A0
A0 = [[0 for x in range(3)] for y in range(3)]
I have a function called newProb which takes this as an argument and returns another 2D matrix in the following way:-
A1 = newProb(A0)
So, I want to put this code into a loop.
A1 = newProb(A0)
A2 = newProb(A1)
A3 = newProb(A2)
A4 = newProb(A3)
Any help will be appreciated. Thanks!
P.S. I have to make 100 calls to that function in the above way
Rather than trying to create local variables in your loop, you'd be better off storing the results in a list. Your list's index will line up nicely with your naming convention.
A = []
A.append([[0 for x in range(3)] for y in range(3)])
A[1] = newProb(A[0])
A[2] = newProb(A[1])
# ...
You can then easily put this into a loop with a range.
# start the range off by 1
for i in range(1, 10):
A[i] = newProb(A[i - 1])
This could also be written as
for i in range(10):
A.append(newProb(A[i]))
Use a dict:
A = {}
A[0] = [[0 for x in range(3)] for y in range(3)]
for i in range(1, 101):
A[i] = newProb(A[i-1])
You can store your values in a list generated like so:
A = [A0]
for i in range(99):
A.append(newProb(A[i]))
Combining the answers from #jez and #Soviut:
A = []
A.append([[0 for x in range(3)] for y in range(3)])
for i in range(100):
A.append(newProb(A[-1])
A[-1] is the last element in the list.
If you just need the 'final' value, after the 100st loop:
value = [[0 for x in range(3)] for y in range(3)]
for i in range(100):
value = newProb(value)
Round out the answers with a while loop
A = [A0]
while len(A) < 100:
A.append(newProb(A[-1]))

python function making unrequested changes

I have a function (crout) defined in a file called LU.py and another function defined in a different file (invert.py). The contents of the files are:
LU.py
def crout(A,L,U):
N = len(A)
add = 0
#print(L,U)
for i in range(N):
print('b',L[i][i])
U[i][i] = 1
print('a',L[i][i])
#print(L,U)
and invert.py
import LU
def inverse(A):
n = len(A)
B = []
L = []
U = []
for i in range(n):
row = [0 for j in range(n)]
B.append(row)
L.append(row)
U.append(row)
LU.crout(A,L,U)
return B
M = [[1,2,3],[1,0,1],[2,2,0]]
Mi = inverse(M)
A = [[1,2,3],[1,0,1],[2,2,0]]
L = [[0,0,0],[0,0,0],[0,0,0]]
U = [[0,0,0],[0,0,0],[0,0,0]]
print('bla')
LU.crout(A,L,U)
Notice that I run the function crout two times from the invert file, once from the inverse function and once from outside the function.
Next, I run the invert.py file using python 2.7.6 on an ubuntu linux machine and I get the following output:
('b',0)
('a',1)
('b',0)
('a',1)
('b',0)
('a',1)
bla
('b',0)
('a',0)
('b',0)
('a',0)
('b',0)
('a',0)
The numbers before the 'bla' which is the call of crout from within inverse, represent the elements of the diagonal in array L. Notice that these values change from 0 ('b') to 1 ('a') as I change the values in U (which off course should not happen!). On the other hand, when I call crout from outside the function inverse the values in L remain unchanged after changing U, which off course is what should happen.
Any ideas about why this is happening would be very much appreciated!
Carlos
In inverse, you append the row variable to each of B, L, and U.
for i in range(n):
row = [0 for j in range(n)]
B.append(row)
L.append(row)
U.append(row)
Now each list contains a reference to the same row value. changing a value in one of the lists will change the accompanying value in each other one. If this is not the desired behavior, create a new row for each list.
for i in range(n):
B.append([0 for j in range(n)])
L.append([0 for j in range(n)])
U.append([0 for j in range(n)])
If this looks a bit inelegant to you, it may be useful to make an independent function for matrix creation logic.
def make_square_matrix(size):
return [[0]*size for b in range(size)]
def inverse(A):
n = len(A)
B = make_square_matrix(n)
L = make_square_matrix(n)
U = make_square_matrix(n)
LU.crout(A,L,U)
return B

Categories