I am a Python beginner and a bit confused about enumerate function in summing the polynomial problem in the following SO thread:
Evaluating Polynomial coefficients
The thread includes several ways to solve the summing of polynomials. I understand the following version well:
def evalP(lst, x):
total = 0
for power in range(len(lst)):
total += (x**power) * lst[power] # lst[power] is the coefficient
return total
E.g. if I take third degree polynomial with x = 2, the program returns 15 as I expected based on pen and paper calculations:
evalP([1,1,1,1],2)
Out[64]:
15
But there is another, neater version of doing this that uses enumerate function:
evalPoly = lambda lst, x: sum((x**power) * coeff for power, coeff in enumerate(lst))
The problem is that I just can't get that previous result replicated with that. This is what I've tried:
coeff = 1
power = 3
lst = (power,coeff)
x = 2
evalPoly(lst,x)
And this is what the program returns:
Out[68]:
5
Not what I expected. I think I have misunderstood how that enumerate version takes on the coefficient. Could anyone tell me how I am thinking this wrong?
The previous version seems more general as it allows for differing coefficients in the list, whereas I am not sure what that scalar in enumerate version represents.
You should call evalPoly with the same arguments as evalP, e.g. evalPoly([1,1,1,1],2)
When you call evalPoly([3,1],2), it return 3*2^0 + 1*2^1 which equals 5.
Related
I am learning how to code and wondered how to take the mean without using a builtin function (I know these are optimized and they should be used in real life, this is more of a thought experiment for myself).
For example, this works for vectors:
def take_mean(arr):
sum = 0
for i in arr:
sum += i
mean = sum/np.size(arr)
return mean
But, of course, if I try to pass a matrix, it already fails. Clearly, I can change the code to work for matrices by doing:
def take_mean(arr):
sum = 0
for i in arr:
for j in i:
sum += i
mean = sum/np.size(arr)
return mean
And this fails for vectors and any >=3 dimensional arrays.
So I'm wondering how I can sum over a n-dimensional array without using any built-in functions. Any tips on how to achieve this?
You can use a combination of recursion and loop to achieve your objective without using any of numpy's methods.
import numpy as np
def find_mean_of_arrays(array):
sum = 0
for element in array:
if type(element) == type(np.array([1])):
sum += find_mean_of_arrays(element)
else:
sum += element
return sum/len(array)
Recursion is a powerful tool and it makes code more elegant and readable. This is yet another example
Unless you need to mean across a specific axis, the shape of the array does not matter to compute the mean. Making your first solution possible.
def take_mean(arr):
sum = 0
for i in arr.reshape(-1): # or arr.flatten()
sum += i
mean = sum/np.size(arr)
return mean
I have just started with Python programming language. I tried to write a function which takes input either a list or multiple integers to find their product. I am trying to find the product of first million natural numbers but its displaying an MemoryError.
def product(*arg):
answer=1
if type(arg) == tuple:
arg=str(arg)
arg=arg.lstrip('[(')
arg=arg.rstrip('],)')
arg=arg.split(',')
for i in arg:
answer*=int(i)
return answer
else:
for i in arg:
answer*=int(i)
return answer
j=range(1,1000000,1)
j=list(j)
print(product(j))
Steps:
I convert the range object into list object if i am to pass a list as
argument
Now, within the function, i try to split the tuple by converting it
string.
I convert the resultant string into a list and then loop over the
elements to find the product
Q1: How to avoid the memory error as i try to find the product of first Million natural numbers?
Q2 How to improve this code?
You can use a Generator in Python.
def generate_product():
r = 1
for i in range(1,1000000):
r *= i + 1
yield r
list(generate_product())[0]
It is more memory efficient and better in terms of performance.
To calculate the product of all numbers from 1 to 1 million use a simple loop:
r = 1
for l in range(1,1000000):
r*=(i+1)
print(res)
But keep in mind that the result will be a pretty big number.
That means that your calculation might take long and the resulting number will need a lot memory.
EDIT Then i missread your question a little. This is a function that multiplies the elements in a list:
def multiply_list_elements(_list):
result = 1
for element in _list:
result*=element
return result
multiply_list_elements([1,2,3,4])
>>> 24
The memory error probably came from the huge number as #ZabirAlNazi calculated so nicely.
All of the solution is fine, but one point to make - your question is equivalent to find the factorial of 1 million.
The number of digits of n! = log10(1) + log10(2) + ... log10(n)
import math
num_dig = 1
for i in range(1,1000000):
num_dig += math.log10(i)
print(num_dig)
So, the number of digits in your answer is 5565703 (approx.).
That's only the final n, if you also want the intermediate results it will require squared memory O(m^2).
import math
ans = 1
for i in range(2,1000001):
ans *= i
print(ans)
N.B: You can approximate with logarithms and Stirling numbers with faster run-time.
A very simple solution would be:
def prod_of():
p=1
for i in range(1,1000000):
p* = i
print(p)
I have to Write a python function that can solve any quadratic equation in the form: ax2 + bx + c = 0, also handle the special case when some of the coefficients are zero, I have to write the function with 3 optional keyword arguments, with the default value of 0. In this way, one can use this function with any order of coefficients as long as the quadratic term is a, the linear is b and the constant is c. Also, one can leave out coefficients if they are 0.
and I have to return a list based on the following conditions: From these coefficients, calculate every real solution and return them as a list, not longer than 2.
Return None if all the coefficients are zero, because in that case you would have infinite number of solutions.
If there is no solution or only complex ones, then return an empty list.
If there is a real root with multiplicity 2, then return a one long list.
However the problem is that I didn't know how to set the default values of a dictionary when I get an empty dictionary as an input. Thank you in advance for your help!
This is my code
import math
def quadratic_solve(**dictr):
List=[]
x1=dictr['a']
x2=dictr['b']
x3=dictr['c']
delta=x1*x1-4*x2*x3
if (x1==0 and x2==0 and x3==0):
return None
if (x1==0):
List.append(-x3/x2)
return List
if(dictr['b']*dictr['b']-4*dictr['a']*dictr['c']<0) :
return List
if(x2*x2-4*x1*x3>0) :
List.append((-x2+math.sqrt(delta))/2*x1)
List.append((-x2-math.sqrt(delta))/2*x1)
return List
You could make better use of Python's feature to reduce the amount of code (i.e. focus on the essential conditions):
def quadratic_solve(params):
a,b,c = [params.get(p,0) for p in "abc"] # get this out of the way early
if a==0: return [] if b==0 else [-c/b] # linear equation
b2_4ac = b*b-4*a*c # part under the square root
if b2_4ac < 0: return [] # complex result
p,n = (-b+b2_4ac**0.5)/2/a, (-b-b2_4ac**0.5)/2/a # + or - square root results
return [p] if p==n else [p,n] # one or two solutions
quadratic_solve({'a':2,'b':3}) # [0.0, -1.5]
For lack of a Latex editor, here is a picture of a piecewise function that I wish to plot using Sympy. I want to pass in two arrays of the coefficients and a value for x, then evaluate it and plot the function. (Edit : there are exactly one more p than there are alphas, image updated)
This is my attempt so far (alpha and p are lists/arrays, t is a number):
def getf(alpha,p,t):
#Create the argument list of tuples for the SymPy.Piecewise function
argtuples = []
for n,number in enumerate(alpha):
if n == 0:
argtuples.append((p[0]*x, x<alpha[0]))
elif 0<n and n<list(enumerate(alpha))[-1][0]:
argtuples.append((p[0]*alpha[0] + Sum(p[i]*(alpha[i] - alpha[i-1]),(i,1,n)) + p[n+1]*(x-alpha[n]), alpha[n-1] <= x < alpha[n]))
else:
argtuples.append((p[0]*alpha[0] + Sum(p[i]*(alpha[i] - alpha[i-1]),(i,1,n)) + p[n+1]*(x-alpha[n]), x>=alpha[n]))
f = Piecewise(argtuples)
return f(t)
from sympy import Piecewise, Sum
from sympy.abc import x, i
getf([10000,50000,100000,1000000],[0.05,0.08,0.15,0.30,0.40],1000001)
However, I'm getting the error "list indices must be integers or slices, not Symbol". How can I reference the coefficient values that I have passed into the function, given that the array could be any length?
You cannot use a symbolic index on a Python list (here i is symbolic, since you are importing it from abc). If you know the list ahead of time, you should use the Python sum function to sum the values, instead of Sum.
sum(p[i]*(alpha[i] - alpha[i-1]) for i in range(1, n))
There is also another problem, which is that you have alpha[n-1] <= x < alpha[n]. This unfortunately won't work, due to the way Python handles chained inequalities. You have to write this as And(alpha[n-1] <= 1, x < alpha[n]) Otherwise you will get TypeError: cannot determine truth value of Relational.
Basically this algorithm I'm writing takes as input a List L and wants to find a number x such that all items in L, i, minus x squared and summed are minimized. Find minimum x for the sum of abs(L[i]-x)**2. So far my algorithm is doing what it's supposed to, just not in the cases of floating. I'm not sure how to implement floating. For example [2, 2, 3, 4] ideally would yield the result 2.75, but my algorithm isn't currently capable of yielding floating integers.
def minimize_square(L):
sumsqdiff = 0
sumsqdiffs = {}
for j in range(min(L), max(L)):
for i in range(len(L)-1):
sumsqdiff += abs(L[i]-j)**2
sumsqdiffs[j]=sumsqdiff
sumsqdiff = 0
return min(sumsqdiffs, key=sumsqdiffs.get)
It is easy to prove [*] that the number that minimizes the sum of squared differences is the arithmetic mean of L. This gives the following simple solution:
In [26]: L = [2, 2, 3, 4]
In [27]: sum(L) / float(len(L))
Out[27]: 2.75
or, using NumPy:
In [28]: numpy.mean(L)
Out[28]: 2.75
[*] Here is an outline of the proof:
We need to find x that minimizes f(x) = sum((x - L[i])**2) where the sum is taken over i=0..n-1.
Take the derivative of f(x) and set it to zero:
2*sum(x - L[i]) = 0
Using simple algebra, the above can be transformed into
x = sum(L[i]) / n
which is none other than the arithmetic mean of L. QED.
I am not 100% sure this is the most efficient way to do this but what you could do is mantain the same algorithm that you have and modify the return statement.
min_int = min(sumsqdiffs, key=sumsqdiffs.get)
return bisection(L,min_int-1,min_int+1)
where bisection implement the following method: Bisection Method
This works iff there is a single minimum for the function in the analyzed interval.