matrix addition giving wrong answer - python-3.x

I am from java background, I am learning python matrix operation. I have an assignment question to add two matrices manually I can't figure out the error in my logic. need help thank you
x = [[12,7,3],[4 ,5,6],[7 ,8,9]]
y = [[5,8,1],[6,7,3],[4,5,9]]
row = len(x)
col = len(x[0])
ans = [[0] * col] * row
for i in range(len(x)):
for j in range(len(x[i])):
ans[i][j] = x[i][j] + y[i][j]
print()
print(ans)
output :
[[11, 13, 18], [11, 13, 18], [11, 13, 18]]

The problem is here:
ans = [[0]*col]*row
This statement creates row number of objects, where each object is [[0]*col]. What this means is that, each "sub-list" in the list is pointing to the same list.
(More information about this behaviour here: List of lists changes reflected across sublists unexpectedly)
You can verify that by checking the id values of ans[0],ans[1] and so on:
>>> a = [[0]*col]*row
>>>
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> id(a[0])
140336190913992
>>> id(a[1])
140336190913992
>>> id(a[2])
140336190913992
This means, if we set a[0][1] = 10 (say), then EACH sub-list will have the the value 10 set. This is because all the lists point to the same list.
i.e.
>>> a[0][1] = 10
>>> a
[[0, 10, 0], [0, 10, 0], [0, 10, 0]]
Now, how do we avoid this?
You can do so by initiliasing the ans list in a different way, as in:
b = [[0 for x in range(col)] for y in range(row)]
You can verify that all the sub-lists point to different addresses by using id again:
>>> id(b[0])
140336190512520
>>> id(b[1])
140336190765000
>>> id(b[2])
140336197031816
So now if you run your original program, you will get desired results.
TLDR; your modified program looks like this:
x = [[12,7,3],[4 ,5,6],[7 ,8,9]]
y = [[5,8,1],[6,7,3],[4,5,9]]
row = len(x)
col = len(x[0])
ans = [[0 for x in range(col)] for y in range(row)]
for i in range(len(x)):
for j in range(len(x[i])):
ans[i][j] = x[i][j] + y[i][j]
print(ans)

Related

Get the distance from every element in a list to any other element

I have a list:
l = [10,22,3]
I'm trying to create a function that returns the distances (how close they are in the list itself), such that elements on the left of any element has a negative value, and those on its right has a positive value:
#optimal output
dis = [[0,1,2],[-1,0,1],[-2,-1,0]]
Is there a quick way to do that?
You could try a nested for-in loop. The idea here is to just retrieve the indexes of each value and its distance from other values.
nums = [10, 22, 3]
distances = []
for i in range(len(nums)):
for n in range(len(nums)):
distances.append(i-n)
print(distances)
Output:
[0, -1, -2, 1, 0, -1, 2, 1, 0]
Also, never name a variable l, because it looks like a 1.
Based on Leonardo's answer, to do what the OP commented:
nums = [10, 22, 3]
distances = []
for i in range(len(nums)):
temp = []
for n in range(len(nums)):
temp.append(n-i)
distances.append(temp)
print(distances)
Output:
[[0, 1, 2], [-1, 0, 1], [-2, -1, 0]]

All test cases passed except one which is throwing key error

We are given a directed graph, with nodes labeled 0, 1, ..., n-1 and each edge is either red or blue, and there could be self-edges or parallel edges.
Each [i, j] in red_edges denotes a red directed edge from node i to node j. Similarly, for blue_edges.
Return an array 'answer' of length n, where each answer[X] is the length of the shortest path from node 0 to node X such that the edge colors alternate along the path (or -1 if such a path doesn't exist).
I'm not getting where's the problem in the code.
n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
d={}
result=[-1]*(n)
for i in red_edges:
if i[0] not in d:
d[i[0]]=[i[1]]
else:
d[i[0]].append(i[1])
if i[0]==0:
result[i[1]]=1
#print(d)
for j in blue_edges:
if j[0] not in d:
d[j[0]]=[j[1]]
else:
d[j[0]].append(j[1])
if j[0]==0:
result[j[1]]=1
elif j[0]!=0:
if j[0] in d[0]: #This is Line 24 which is throwing error.
result[j[1]]=2
else:
pass
if 0 in d[0]:
result[0]=1
else:
result[0]=0
#print(d)
print(result)
Key in 'd' is equal to the starting node and value in a key-value pair has a list in which all the endpoints corresponding to that key are inserted.
Moreover, in each for loop, I'm also preparing my result array if any edge is present between node zero and node equal to the index of the result array. e.g, I'll insert 1 in result array for index 1 if it has a direct link with node zero else I'll keep it as -1. And if any index has indirect link( as in test case 2: blue_edges =[[2,1]]) then I'll check in d[0] if first element of blue_edges is present. If it is present then I'll insert 2 else -1.
expected=actual=[0,1,-1]
expected=actual=[0,1,-1]
expected=actual=[0,1,1]
expected=[0,-1,-1] but in 4th case it is throwing an error.
Line 24: KeyError: 0
I switched to using defaultdict(list) so that if d is empty for some value, you'll just get an empty list.
In your case - it eliminates the error and logically matches the if.
it also help clean up many if/elses.
try this:
from collections import defaultdict
cases = [
(3, [[0, 1], [1, 2]], []),
(3, [[0, 1]], [[2, 1]]),
(3, [[0, 1]], [[1, 2]]),
(3, [[1, 0]], [[2, 1]]),
]
for n, red_edges, blue_edges in cases:
d = defaultdict(list)
result = [-1] * n
result[0] = 0
for src, dst in red_edges:
d[src].append(dst)
if src == 0:
result[dst] = 1
for src, dst in blue_edges:
d[src].append(dst)
if src == 0:
result[dst] = 1
else:
if src in d[0]:
result[dst] = 2
print(result)
Output:
[0, 1, -1]
[0, 1, -1]
[0, 1, 2]
[0, -1, -1]

Efficiently Loop Through Millions of Elements

I have a list of 262144 elements in a list created through "itertools.product". Now I have to loop over these elements and multiply it with all other elements, which is taking too much time. (I don't have any issue of memory / cpu)
elements = []
for e in itertools.product(range(4), repeat=9):
elements.append(e)
for row in elements:
for col in elements:
do_calculations(row, col)
def do_calculations(ro, co):
t = {}
t[0] = [multiply(c=ro[0], r=co[0])]
for i in range(1, len(ro)):
_t = []
for j in range(i+1):
_t.append(multiply(c=ro[j], r=co[i-j]))
t[i] = _t
for vals in t.values():
nx = len(vals)
_co = ro[nx:]
_ro = co[nx:]
for k in range(len(_ro)):
vals.append(multiply(c=_co[k], r=_ro[k]))
_t = []
for k in t.values():
s = k[0]
for j in range(1, len(k)):
s = addition(c=s, r=k[j])
_t.append(s)
return _t
def addition(c, r) -> int:
__a = [[0, 3, 1, 2],
[3, 2, 0, 1],
[0, 3, 2, 1],
[1, 0, 2, 3]]
return __a[c][r]
def multiply(c, r) -> int:
__m = [[0, 0, 0, 0],
[0, 1, 2, 3],
[0, 3, 1, 2],
[0, 2, 3, 1]]
return __m[c][r]
it is taking too much time to process single col with rows....
can any one help me in this?
regards
Not much of a python guy but
make sure col is a higher number than row (small optimization, but optimization nevertheless)
use a multiprocessing library (alink). that should cut the calculation time.
(as noted in comment by #Skam, multithreading does not increase performance in such case)
also, you might consider some optimizations in the calculation itself.

Returning the N largest values' indices in a multidimensional array (can find solutions for one dimension but not multi-dimension)

I have a numpy array X, and I'd like to return another array Y whose entries are the indices of the n largest values of X i.e. suppose I have:
a =np.array[[1, 3, 5], [4, 5 ,6], [9, 1, 7]]
then say, if I want the first 5 "maxs"'s indices-here 9, 7 , 6 , 5, 5 are the maxs, and their indices are:
b=np.array[[2, 0], [2 2], [ 2 1], [1 1], [0 , 2])
I've been able to find some solutions and make this work for a one dimensional array like
c=np.array[1, 2, 3, 4, 5, 6]:
def f(a,N):
return np.argsort(a)[::-1][:N]
But have not been able to generate something that works in more than one dimension. Thanks!
Approach #1
Get the argsort indices on its flattened version and select the last N indices. Then, get the corresponding row and column indices -
N = 5
idx = np.argsort(a.ravel())[-N:][::-1] #single slicing: `[:N-2:-1]`
topN_val = a.ravel()[idx]
row_col = np.c_[np.unravel_index(idx, a.shape)]
Sample run -
# Input array
In [39]: a = np.array([[1,3,5],[4,5,6],[9,1,7]])
In [40]: N = 5
...: idx = np.argsort(a.ravel())[-N:][::-1]
...: topN_val = a.ravel()[idx]
...: row_col = np.c_[np.unravel_index(idx, a.shape)]
...:
In [41]: topN_val
Out[41]: array([9, 7, 6, 5, 5])
In [42]: row_col
Out[42]:
array([[2, 0],
[2, 2],
[1, 2],
[1, 1],
[0, 2]])
Approach #2
For performance, we can use np.argpartition to get top N indices without keeping sorted order, like so -
idx0 = np.argpartition(a.ravel(), -N)[-N:]
To get the sorted order, we need one more round of argsort -
idx = idx0[a.ravel()[idx0].argsort()][::-1]

how to fix python fibonacci sequence script?

My assignment is to create a function that produces 3 lists of the numbers in the fibonacci sequence starting at 0. Here is my code so far.
def fibList(n):
a = 0; b = 1; fibList = []
if n <= 0:
return
elif n == 1:
fibList = [a]
elif n == 2:
fibList = [a,b]
else:
for i in range(0,n):
a, b = b, a + b
fibList.append(b)
return fibList
def main():
print (fibList(4))
print (fibList(10))
print (fibList(-4))
what i want my output to look like is [0,1,1,2] for 4, [0,1,1,2,3,5,8,13,21,34,55] for 10, and [] for -4
My issue begins with fibList(4) currently giving an output of [1, 2, 3, 5] and fibList(10) gives an output of [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] and for -4 I get "None" instead of a [].
If I type in fibList(1) I get [0] and for fibList(2) I get [0, 1], but when i test fibList(3) the first 0 and 1 are lost, giving me [1,2,3]
How would I go about making it so any number above 3 starts with [0, 1, 1, 2...]? My main issue is getting the 0 and 1 to be the first two numbers in the sequence and getting fibList(-4) to produce a [].
any help or tips would be greatly appreciated :-)
All that you are missing is to add an empty list in the case of less than or equal to zero, and recurse correctly over your range of Fibonacci numbers greater than 2. Making those small changes like so:
def fibList(n):
if n <= 0:
fibnums = []
elif n == 1:
fibnums = [0]
elif n >= 2:
fibnums = [0, 1]
for i in range(2,n):
fibnums.append(fibnums[i-1]+fibnums[i-2])
return fibnums
Note that this recursive method can get quite slow for large numbers, if that is of concern to you with your program. Best of luck!
With these changes,
print (fibList(4)) => [0, 1, 1, 2]
print (fibList(10)) => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print (fibList(-4)) => []
You did not quite define your function. Should the resulting list have n values [f(0), ..., f(n-1)] or n+1 values [f(0), ..., f(n)]? Your examples are contradictory: the 'expected' output for 4 has 4 values ending with f(3) while that for 10 has 11 values ending with f(10).
I am going to assume that the latter is correct. Here is a revised version of your fast iterative solution. (If my assumption is wrong, stop the range at n instead of n+1.)
def fibs(n):
"Return [fib(0), ..., fib(n)."
ret = [0, 1] # fib(0), fib(1)
a, b = ret
if n <= 1:
return ret[:n+1]
else:
for i in range(2, n+1):
a, b = b, a+b # b = f(i)
ret.append(b)
return ret
print(fibs(-4), fibs(0), fibs(2), fibs(4), fibs(10))
#
[] [0] [0, 1, 1] [0, 1, 1, 2, 3] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Resources