Problem in multiplication of 2 dimensional lists - python

Actually i need help to solve a problem related to multiplying 2D lists.
The problem is that I have two lists, a and b:
a = [[-0.104],[-0.047],[-0.046]]
b = [[0.183, 0.366, 0.456], [0.971, 0.156, 0.856]]
I want to multiply each element in a with the corresponding element in the first sub-list of b, such that:
(-0.104 * 0.183) + (-0.047 * 0.366) + (-0.046 * 0.456)
Then, I come again to multiply each element in a with the corresponding element in the second sub-list of b, such that:
(-0.104 * 0.971) + (-0.047 * 0.156) + (-0.046 * 0.856)
The result should be 2 elements.
So, I've implements my own code using Python, but unfortunately the code didn't work correctly.
So, I need some help to fix the error in my code.
The code is below:
a= [[-0.104],[-0.047],[-0.046]]
b= [[0.183, 0.366, 0.456], [0.971, 0.156, 0.856]]
sumR=0
res2=[]
for i in range(0, len(a)):
for j in range(0, len(b[0])):
for k in range(j):
r= (a[i][j]*b[k][j])
sumR=sumR+r
res2.append(round(sumR,6))
print(res2)

Your question is something common to programmers coming to Python from a different language.
Try using what Python's strength are, instead of writing C/Java/whatever in Python:
xss = [[-0.104],[-0.047],[-0.046]]
yss = [[0.183, 0.366, 0.456], [0.971, 0.156, 0.856]]
answers = [sum([xs[0] * y for xs, y in zip(xss, ys)]) for ys in yss]
print(answers)
(or, if you don't object to using Python's further strengths, i.e. its many great third party libraries, use something like numpy, like #GilPinsky suggests)
A bit of an explanation of the list comprehension: something like [ys for ys in yss] causes Python to loop over yss, assigning each value of yss to ys in turn, collecting the results in a list. You can of course apply an operation to ys to make it useful.
zip(xss, ys) pairs each element of xss with an element from ys and returns an iterable. [xs, y for in zip(xss, ys)] would get you a list of all the tuples from that combination. And so sum([xs[0] * y for xs, y in zip(xss, ys)]) gets you the sum of all the products of each pair from xss and ys. It has xs[0] because elements from xss are themselves lists and you're only interested in the first element of each.
I've renamed the variables to make it a bit easier to keep track of what's what. x is just some value, xs is a list of a number of values, xss is a list of such lists, etc. - similar for y and ys.

Not sure if this is the answer you are looking for: [-0.05721, -0.147692]
a= [[-0.104],[-0.047],[-0.046]]
b= [[0.183, 0.366, 0.456], [0.971, 0.156, 0.856]]
sumR=0
res2=[]
for i in range(0, len(b)):
sumR = 0
for j in range(0, len(a)):
# every list in a as only 1 element
r= (a[j][0]*b[i][j])
# print(a[j][0],b[i][j],end = " + ")
sumR=sumR+r
#print()
res2.append(round(sumR,6))
print(res2)
Uncomment the print statements to see how the calculation is going

A better solution will be to not use loops in this case.
Take note that what you are trying to implement is a matrix multiplication by a vector, so you can use numpy to do this efficiently as follows:
import numpy as np
a = np.array([[-0.104], [-0.047], [-0.046]])
b = np.array([[0.183, 0.366, 0.456], [0.971, 0.156, 0.856]])
res2 = (b # a).tolist()

Related

Check elements sum in two different list [duplicate]

I've read that one of the key beliefs of Python is that flat > nested. However, if I have several variables counting up, what is the alternative to multiple for loops?
My code is for counting grid sums and goes as follows:
def horizontal():
for x in range(20):
for y in range(17):
temp = grid[x][y: y + 4]
sum = 0
for n in temp:
sum += int(n)
print sum # EDIT: the return instead of print was a mistype
This seems to me like it is too heavily nested. Firstly, what is considered to many nested loops in Python ( I have certainly seen 2 nested loops before). Secondly, if this is too heavily nested, what is an alternative way to write this code?
from itertools import product
def horizontal():
for x, y in product(range(20), range(17)):
print 1 + sum(int(n) for n in grid[x][y: y + 4])
You should be using the sum function. Of course you can't if you shadow it with a variable, so I changed it to my_sum
grid = [range(20) for i in range(20)]
sum(sum( 1 + sum(grid[x][y: y + 4]) for y in range(17)) for x in range(20))
The above outputs 13260, for the particular grid created in the first line of code. It uses sum() three times. The innermost sum adds up the numbers in grid[x][y: y + 4], plus the slightly strange initial value sum = 1 shown in the code in the question. The middle sum adds up those values for the 17 possible y values. The outer sum adds up the middle values over possible x values.
If elements of grid are strings instead of numbers, replace
sum(grid[x][y: y + 4])
with
sum(int(n) for n in grid[x][y: y + 4]
You can use a dictionary to optimize performance significantly
This is another example:
locations = {}
for i in range(len(airports)):
locations[airports["abb"][i][1:-1]] = (airports["height"][i], airports["width"][i])
for i in range(len(uniqueData)):
h, w = locations[uniqueData["dept_apt"][i]]
uniqueData["dept_apt_height"][i] = h
uniqueData["dept_apt_width"][i] = w

most efficient way to modify each element in multiple lists together?

Let's say I have 3 lists
a = [1.12, 2.23, 3.34]
b = [2.12, 3.23, 4.34]
c = [3.12, 4.23, 5.34]
my goal is to round the numbers down to 1 decimal. so I have this custom function:
import math
def round_down(n, decimals=0):
multiplier = 10 ** decimals
return math.floor(n * multiplier) / multiplier
May I ask what is the most efficient way of operating on each element in each object? In this easy example I could write a loop for each of the 3 objects, such as:
for i in np.range(len(a)):
a[i] = round_down(a[i], decimals=1)
However, in my work, I have many more lists of various lengths and I really don't want to code them one by one. Is there a way to iterate through a list of objects? or process them in parallel?
Just like you use a for loop to avoid coding for every single element, use a for loop to iterate over all your lists:
my_lists = [a, b, c]
for l in my_lists:
for i in np.range(len(l)):
l[i] = round_down(l[i], decimals=1)
combine_array = [a, b, c]
for p in combine_array:
for i in np.range(len(p)):
p[i] = round_down(p[i], decimals=1)

Project Euler #8 : problem with the product of larger adjacent slices

Useful Links: Project Euler #8, I don't understand where I'm going wrongProject Euler 8
My approach to the problem involves:
1) Starting from the first digit, slicing the integer into required slice lengths (13 here)
2) Creating a list of individual elements in a particular slice.
3) Evaluating the product of the digits in the list using numpy.
4) Appending the results of multiplication in a separate list.
5) Printing the maximum valued product from the list
Here is the attempt:
import numpy
import math
i = 7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
i = str(i)
multiple_list = []
for j in range(len(i)-14):
p = i[j:j+13]
l = list(p)
l = [int(x) for x in l]
y = numpy.prod(l)
multiple_list.append(y)
print(max(multiple_list))
The output of the above block of code is : 2091059712
Which of course is the wrong answer! Please help me in figuring out the reason for this discrepancy.
Why complicate your program? You can make it simpler -
s = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
largest_product = 0
for i in range(0, len(s) - 13):
product = 1
for j in range(i, i + 13):
product *= int(s[j: j + 1])
if product > largest_product:
largest_product = product
print(largest_product)
The reason your code doesn't work is because numpy uses 32 bits integers, like C. You are experiencing the same problem of the question you linked. You can find a complete explanation in this answer:
https://stackoverflow.com/a/39089671
To solve your code you can use a for loop to multiply the 13 digits instead of using numpy.prod()
You could also do it with a list comprehension:
from numpy import prod
n = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
p = max(prod([int(d) for d in a]) for a in zip(*[n[i:] for i in range(13)]))
print(p)

ValueError: setting an array element with a sequence

These two sections my code are giving the following error message.
def Simpsons(a, b, n, f, x):
h=(b-a)/n
s = 0.
step = a + h
for i in range(1, int(n/2)):
s += 4*f(x)
#step += 2*h
step = a + 2 * h
for i in range(2, int(n/2 - 1)):
s += 2*f(x)
#step += 2 * h
area = (h/3) * (f(a) + f(b) + s)
return area
and
for i in range(0, len(list_n)):
for j in range(0, len(Functions)):
x = np.linspace(a, b, list_n[i])
error_simp[j, i] = Exact_intergrals[j] - Simpsons(0, 1, list_n[i], Functions[j], x)
print(error_simp)
Give this message:
error_simp[j, i] = Exact_intergrals[j] - Simpsons(0, 1, list_n[i], Functions[j], x)
ValueError: setting an array element with a sequence.
Why is this? everything I have tried does not get rid of it.
I guess you are trying to load array into error_simp[j,i] which might be able to contain only float numbers.
Here is a simple example which illustrates this error:
import numpy
b = numpy.zeros(5)
b[0] = numpy.zeros(5) - 1
Produces the same error.
Looks like either Simpsons function returns an array or Exact_intergrals[j] contains an array.
If you need to save arrays in error_simp matrix, try to add one more dimension:
error_simp = np.zeros((rows, cols, additional_dimension_size))
(Another option is to explicitly set dtype=object option in constructor, but it's much slower and not recommended).
There are a few similar questions that might help: this one and this
Your Simpsons function when given an array returns an array of the same size:
In [335]: Simpsons(0,1,10, lambda x:x**2, np.linspace(0,1,3))
Out[335]: array([ 0.03333333, 0.2 , 0.7 ])
You don't show how error_simp is initialized. The use error_simp[j, i]=... and the error suggests that
np.zeros((n,m), float)
or something like that.
For further help you need to specify what you expect to put in error_simp. If x is the same for all elements, you could create a matching 3d array. If x has different lengths, it will have to be dtype=object. But I like to discourage this usage by beginners. Such an array is little more than a glorified (or debased) list of lists. It's easy to have unrealistic expectations of what you can do with such an array.
=========
Looking more carefully at
for i in range(0, len(list_n)):
for j in range(0, len(Functions)):
x = np.linspace(a, b, list_n[i])
you probably are creating different size x. You don't show list_n, but it probably is something like [10,12,14,...], testing this function for different n.

Obtaining an array of values for coupled nonlinear equations by iterating over input arrays

I am attempting to solve a coupled system of nonlinear equations:
x(x+2y)/(1-x-y) = A
y(x+2y)/x = B
where A and B are elements in two different arrays of identical size.
I have 10,000 values for A in an array, and 10,000 values for B in another array.
I need to determine x[i] and y[i] using A[i] and B[i]. However, when I do the following:
def Eqs(z):
x, y = z
for i in A and B:
return (x*(x + 2*y) - A[i]*(1 - x - y), y*(x + 2*y) - B[i]*x)
x, y = scopt.fsolve(Eqs, (1,1))
I get the following error message:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Using random arrays of appropriate size for A and B, Could someone please (1) explain why I'm getting that particular error message, and (2) suggest a work-around?
The line for i in A and B: doesn't make much sense. A and B is a binary logical operation on the arrays A and B, which is neither valid nor the operation you need.
What you want to do is probably something like for a, b in zip(A, B):. This yields the scalars a and b in every iteration. So a = A[i] and b = B[i]. zip creates pairs of values from A and B, which are than available as a and b within the for-loop.
Alternatively you can iterate using the index i: for i in range(len(A)):
There is another issue with the code: return will stop the loop and leave the method in the very first iteration. So you either create two lists for the return values, fill it throughout the for-loop and return it at the end of Eqs. Or you shorten it using list comprehensions:
return [x*(x + 2*y) - a*(1 - x - y) for a in A], [y*(x + 2*y) - b*x for b in B]
This should yield two lists.

Categories