How to do a sum in python - python

I was wondering how one can represent a sum in python without loops like here
where we have:
def rosen(x):
"""The Rosenbrock function"""
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
My function is the following: V(theta) = Sum(i=1->N)[a0*(cos(i*theta)]
Thank you in advance for your help :):)

Your formula is:
V(theta) = Sum(i=1->N)[a0*(cos(i*theta)]
which means: sum all values of a0*(cos(i*theta) for a given value theta in the range 1 to and including N.
This becomes something like this in Python:
def V(theta, N):
return sum(a0*(cos(i*theta)) for i in range(1, N + 1))
Note that you have to pass theta and N to the function. Also note that we are using N + 1 to make sure N is included (as range iterates over the values until, but not including, the last value).

something like:
def V(theta,N):
return sum(a0*(cos(i*theta) for i in range(1,N+1))
print V(theta,N)
or you can use lambda:
V =lambda theta,N : sum(a0*(cos(i*theta) for i in range(1,N+1))
print V(theta,N)

Your shown example uses no math functions, just basic arithmetical operations. That's why it works as shown, but math.cos doesn't support lists and so will not work this way.
If you really want to get around without any for, you should use numpy. Numpy's math functions support lists (actually arrays).
This way you can write something like:
from numpy import *
def fun(theta):
return a0*sum(cos(arange(1,N+1)*theta))
Should you be doing a lot of this kind of calculations, it is best to use numpy.

Related

Efficient methods of accessing the outputs of generators

I'm working through some exercises in my python book and was asked to implement an infinite product to estimate the sine function depending on some amount of iterations k. The code I wrote is the following:
def approx_sin(x,k):
def u(k):
if k==0:
return x
else:
return (1-((x**2)/((k**2)*(pi**2))))
u0=u(0)
yield u0
for n in range(1,k+1):
u0=u(n)*u0
yield u0
Which works as intended. Now I'm asked to sketch this function on some interval for different values of k, meaning we have to extract some values from the generator. To do this, I create the following function:
def sin_sketch(x,k):
return list(itertools.islice(approx_sin(x,k),k,k+1))[0]
And I can now plot sin_sketch(x,n) for some linspace x and a given value for n. My question boils down to, there has to be a better/more time efficient way to extract the value produced by itertools.islice(approx_sin(x,k),k-1,k) rather then converting it to a list, then taking its only element. Any tips?
Creating a list of a single element should not be much of a problem, performance-wise, but you could e.g. also use next to get the first (and only) element in that islice. In this case, the upper bound does not matter at all.
def sin_sketch(x, k):
return next(itertools.islice(approx_sin(x, k), k-1, k))
Or, instead of islice, use next with enumerate and check the index. I did not time which of those is faster, but this might be a bit clearer.
def sin_sketch(x, k):
return next(v for i, v in enumerate(approx_sin(x, k)) if i == k-1)
It seems like a case of Get the nth item of a generator in Python[*]. But I don't particularly like approaches described there, so here's mine.
From what I understand, you want to get k'th value generated by approx_sin(x, k). So let's do just that:
def sin_sketch(x, k):
gen = approx_sin(x, k)
for _ in range(k):
v = next(gen)
return v
This might look a bit bulkier, but I think it's way more explicit and transparent, without requiring itertools.
[*]: Looking through answers there, I found the one that I like even more than my own: https://stackoverflow.com/a/72817329/9288580
I would simplify your appox function a little to become
from math import pi
from itertools import count
def approx_sin(x):
product = 1
for n in count(1):
product = product * (1-((x**2) / ((n**2) * (pi**2))))
yield x * product
that might make the second part of the question more straightforward.

Incrementation to a list's for method

I am trying to implement an incrementation to a previously defined variable called sum.
return [sum = sum + number for number in range(a,b)]
Of course this format brings up error but using the similar:
return [sum = number for number in range(a,b)]
The code is faulty but runs. If there's a way to implement it and return sum the code would work.
And also if someone could inform me about the nomenclature I'd forever be grateful.
Here are a few possible answers. What you are using is called a list comprehension.
s += (b*(b-1) - a*(a-1))//2
s += sum([n for n in range(a,b)])
for n in range(a,b):
s += n
It's not a good idea to name a variable sum as it is a built in Python function.
Try the following:
return sum([number for number in range(a,b)])
As said in the commentaries, sum is a python built-in function which, given an array, it returns the result of the addtion of all elements in it
You essentially reimplemented the built-in function sum. Just call the function directly:
return sum(range(a, b))

Find the product of items in the list without using the multiplication sign

I'm new in python and I wrote code to have the product of items in a list without using the multiplication sign:
def witOutmultiply(some_list):
first_num = some_list[0]
result = 0
for n in some_list[1:]:
for i in range(n):
result += first_num
first_num = result
result = 0
return first_num
q =[2,4,5,6,10,15]
print(witOutmultiply(q))
My question is: can I use comprehensions in this case, and can I get the result with just one loop? Thanks
Yes, you can use list comprehension, sum, and range, but no other builtin functions:
q = [2,4,5,6,10,15]
mult = q[0]
for n in q[1:]:
mult = sum(mult for _ in range(n))
print(mult)
#36000
Here is an answer with no loop at all that satisfies your condition of "no multiplication sign." It is therefore very fast. The reduce function repeats an operation between members of an iterable, reducing it to a single value, while the mul function multiplies two numbers. The 1 at the end of the reduce function gives a reasonable value if the iterable (list) is empty. No multiplication sign in sight!
from operator import mul
from functools import reduce
def prod_seq(seq):
"""Return the product of the numbers in an iterable."""
return reduce(mul, seq, 1)
Comprehensions are used to build data structures. A list comprehension builds a list, a dict comprehension builds a dict, etc. Since you want a single value rather than a data structure in your computation, there's no good reason to use a comprehension.
There probably are ways to avoid using two loops, but it's not going to be easy, since your outer loop does several operations, not just one. Most of the easy ways to avoid an explicit loop will just be hiding one or more loops in some function call like sum. I think that for your chosen algorithm (doing multiplication by adding), your current code is quite good and there's no obvious way to improve it.
from numpy import prod
print(prod(q))
#36000

Powerset recursive, list comprehension python3

I'm new to Python3 and are trying to do a recursive powerset function. It should use list comprehension.
I wrote:
def powerset(seq):
if not seq:
return [[]]
return powerset(seq[1:]) + [[seq[0]] + n for n in powerset(seq[1:])]
This function works but I got feedback and was told it was unnecessary to call the function two times. It did to much computing. It should easily be able to compute up to 20 powersets. So how should I do? I can't get it to work without calling the function twice. Thanks.
Just calculate powerset(seq[1:]) once, store it in a variable, and use it twice:
def powerset(seq):
if not seq:
return [[]]
ps = powerset(seq[1:])
return ps + [[seq[0]] + n for n in ps]
The difference to yours is that this way, you use ps twice, but you compute it just once.
Alternatively, you could use a double list-comprehension (if you like that sort of thing...)
def powerset(seq):
return [x for ps in powerset(seq[1:]) for x in ([seq[0]] + ps, ps)] if seq else [[]]
Here, the same temporary variable ps is defined inside the list comprehension. Note, however, that the results will be in a slightly different order this way.
I feel very unclear. I actually don't understand how just assigning it to a variable can change that? It means the same thing?
You seem to think too much in terms of pure math here. In programming, y = f(x) does not mean "y is the same as/synonymous for f(x)", but "assign the result of f(x) to y".

Three lines to find the greatest product in a string of numbers in Python

Full disclosure: this is for an assignment. Simply getting working code is enough, but doing this in three lines gets me extra credit.
I'm trying to take a 1000-digit string and find the largest product of 5 consecutive digits. You may recognize this as Project Euler's Problem #8.
I've tried a lot of options, but I seem to be stuck. I'm working on figuring out if I can make a lambda statement that will work, but I have no experience with lambda so it's evading me.
Here's what I have so far:
for i in range(1, 996):
max = int(number[i+0]) * int(number[i+1]) * int(number[i+2]) * int(number[i+3]) * int(number[i+4]) if max < int(number[i+0]) * int(number[i+1]) * int(number[i+2]) * int(number[i+3]) * int(number[i+4]) else max = max
return max
That doesn't work and triggers SyntaxError: can't assign to conditional expression.
I don't want outright code, or at least not a complete function, but just a little help understanding how I can move forward.
This isn't legal python:
x = y if z else x = w
This is:
x = y if z else w
So is this:
if z: x = y
By the way, there is a one line solution, that is much shorter and clearer than your three.
= appears twice in your (very long) line. Effectively you have this:
max = something if something else max = max
which Python parses as:
max = (something if something else max) = max
And, indeed, you can't assign to a conditional expression, which is that whole thing in the middle.
You probably didn't intend to have the final = max at the end.
In [15]: def myinput(l,n):
...: for x in l:
...: yield l[x:x+n]
...:
In [16]: max([reduce(lambda a,b:a*b, x) for x in myinput(range(1000),5) if len(x)==5])
Out[16]: 985084775273880L
Like recursive mentioned, there is a simple one-liner solution. It involves using the max function - always bad to name variables after builtins!
In Python 2 it looks something like this:
max(reduce(lambda x, y: x*y, map(int, num[i:i+5])) for i in xrange(996))
In Python 3 reduce was removed, so you have to get it through functools:
from functools import reduce
max(reduce(lambda x, y: x*y, map(int, num[i:i+5])) for i in range(996))
Look into:
the built-in max function to find the greatest number in a sequence,
the built-in map function to apply a function to all elements in a list,
the built-in reduce function to obtain a single object as a result of applying a function that returns a single object repeatedly to two elements in a list,
lambda definitions to be able to define function objects that you can pass to map() and reduce(),
and list comprehensions (and generators, which are very similar) to compose the above functions in a one-liner.

Categories

Resources