behaviour of reduce function in python - python

I am confused by the behavior of the reduce function.
In the first example, I get the expected result: (1-1/2) * (1-1/3) = 1/3
>>> reduce(lambda x, y: (1 - 1.0/x) * (1 - 1.0/y), [2,3])
0.33333333333333337
In the second example, I do not get the expected result: (1-1/2) * (1-1/3) * (1-1/5) = 0.2666666
>>> reduce(lambda x, y: (1 - 1.0/x) * (1 - 1.0/y), [2,3,5])
-1.5999999999999996
Can someone please explain me what I am missing?

What you need is a map and reduce:
>>> from functools import reduce
>>> yourlist = [2, 3]
>>> reduce(lambda x, y: x*y, map(lambda x: (1-1/x), yourlist))
0.33333333333333337
>>> yourlist = [2, 3, 5]
>>> reduce(lambda x, y: x*y, map(lambda x: (1-1/x), yourlist))
0.2666666666666667
Because map converts each item to the (1-1/item) and then the reduce multiplies all of them.
Additional remarks:
Instead of the lambda x, y: x * y you could also use the faster operator.mul, for example:
>>> import operator
>>> yourlist = [2, 3, 5]
>>> reduce(operator.mul, map(lambda x: (1-1/x), yourlist))
0.2666666666666667
Thanks #acushner for pointing this out (in the comments).
What went wrong in your function
In this case it's actually quite easy to see what doesn't work, just use a named function and add some prints:
def myfunc(x, y):
print('x = {}'.format(x))
print('y = {}'.format(y))
res = (1 - 1.0/x) * (1 - 1.0/y)
print('res = {}'.format(res))
return res
reduce(myfunc, [2, 3])
# x = 2
# y = 3
# res = 0.33333333333333337
reduce(myfunc, [2, 3, 5])
# x = 2
# y = 3
# res = 0.33333333333333337
# x = 0.33333333333333337
# y = 5
# res = -1.5999999999999996
So it uses the last result as "next" x value. That's why it worked for the length-2-list case but for more elements it simply doesn't apply the formula you want.
Alternative
Instead of using map and reduce you could also use a simple for-loop. It's much easier to get them right and most of the times they are more readable (and in some cases it's faster than reduce).
prod = 1
for item in yourlist:
prod *= 1 - 1 / item
print(prod)
Yes, instead of 1 line it's now 4 lines long but it's easy to understand what is happening (but there might be some edge cases in which that doesn't behave like reduce, for example for empty inputs).
But I generally prefer simple loops over complicated reduce-operations but as always YMMV. :)

EDIT: I approve map/reduce answer above.
To understand why, read this:
https://docs.python.org/2/library/functions.html#reduce
Reduce recursively calls your function on each element of your list with 2 arguments: an accumulator (value of last call) and current element.
So you get:
(1 - 1.0/( (1 - 1.0/2) * (1 - 1.0/3) )) * (1 - 1.0/5)
With:
reduce(lambda acc, x: (1 - 1.0/acc) * (1 - 1.0/x), [2,3,5])
>>-1.5999999999999996

To add to why you get -1.5999999999999996 as your result and for completeness we can compute it using https://docs.python.org/2/library/functions.html#reduce as our guide:
The first iteration will be (which takes our first 2 iterator values of 2 and 3 as x and y):
(1 - 1.0 / 2) * (1 - 1.0 / 3)
which becomes:
0.5 * 0.6666666666666667
which yields:
0.33333333333333337.
We then use 0.33333333333333337 to move on to our next iteration which takes this result as x and our next iteration number of 5 as y:
Therefore, our second iteration will be:
(1 - 1.0 / 0.33333333333333337) * (1 - 1.0/5)
which becomes:
-1.9999999999999996 * 0.8
which yields:
-1.5999999999999996

In your second example you have 3 inputs. You need:
reduce(lambda x, y: (1 - 1.0/x) * (1 - 1.0/y)* (1 - 1.0/z),...

Related

Repeat Higher Order Function

I'm writing a Higher Order that takes a lambda expression, a number, then number of times it has to repeat that. This is what I have:
#Square Root
sqrt = lambda x: x ** (1/2)
#Repeat
def repeat(f,x,r):
return [f(i) for r in x]
Here's what it should do:
>>> repeat(sqrt, 2, 0)
2
>>> repeat(sqrt, 2, 1)
1.4142135623730951
>>> repeat(sqrt, 2, 2)
1.189207115002721
Here's the error message:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "main.py", line 66, in repeat
return [f(i) for r in x]
TypeError: 'int' object is not iterable
This is NOT a repeat because I am asking how to fix MY code, not how to do the problem. Also this is NOT homework, it is simply a project to understand higher order functions better.
Something like this would work if you used a for loop.
#Square Root
sqrt = lambda x: x ** (1/2)
#Repeat
def repeat(f,x,r):
for i in range(r):
x = f(x)
return x
print(repeat(sqrt, 2, 2))
A list comprehension is not the right tool here. You want a single value — a list comprehension always creates a list.
Since this seems like an exercise, in keeping with the style of lambdas and higher order functions, you could recurse with something like:
sqrt = lambda x: x ** (1/2)
rep = lambda f, x, r: f(x) if r < 1 else f(rep(f, x, r - 1))
rep(sqrt, 2, 0)
# 1.4142135623730951
rep(sqrt, 2, 1)
# 1.189207115002721
If r will be large, you may have issues with recursion depth, however.
You could also use functools.reduce
from functools import reduce
sqrt = lambda x: x ** (1/2)
rep = lambda f, x, r: reduce(lambda n, _: f(n), range(r+1), x)
rep(sqrt, 2, 0)
# 1.4142135623730951
rep(sqrt, 2, 1)
# 1.189207115002721
#Square Root
sqrt = lambda x: x ** (1/2)
#Repeat
def repeat(f,x,r):
if r > 0:
return repeat(f,f(x),r-1)
else:
return x
print(repeat(sqrt, 2, 2))
>> 1.189207115002721
a solution using recursion
def repeat(f,x,r):
return [f(i) for r in range(x)]
You are trying to iterate number which is not possible

How to integrate expressions with sympy?

I have a problem integrating an expression:
I need to integrate all terms regardless of the variable,
the expression: -x + 2 * (x - 1)
Expected result: -x**2/2 + 2 * ((x - 1)**2) / 2
the code I'm using:
from sympy import *
x = symbols('x')
expr = - x + factor(2 * (x - 1))
int_1 = integrate(expr)
print(int_1)
generated result: x**2/2 - 2*x
I'm a python beginner...
Thank you!
If you check your result you will find it is the same as the original equation, so the answer is right:
>>> eq = -x + factor(2 * (x - 1))
>>> integrate(eq).diff()
x - 2
>>> eq.expand()
x - 2
This means that the result you got differed from the expected results by a constant and such cases are considered correct in terms of indefinite integration.
It looks like you already learned about autoexpansion (thus the use of factor to keep the 2 from distributing). What you may not realize, however, is that once you pass an expression to a routine it is not required to keep your expression in factored form. It looks like you were expecting that the x - 1 would be treated like x. We can simulate that as
>>> integrate(-x)+integrate(2*y).subs(y,x-1)
-x**2/2 + (x - 1)**2
Using y to represent x - 1 is ok in this case since the results only differ by a constant:
>>> (integrate(x-1) - integrate(y).subs(y ,x-1)).is_constant()
True
It will not, however, be true for all functions of x.
The problem is that you didn't pass any integration limits (from and to), so the only possible answer was the integrated formula.
If for example you want to integrate from 0 to inf, you need to pass this instead
from sympy import *
x = symbols('x')
expr = - x + factor(2 * (x - 1))
int_1 = integrate(expr, (x,0, float('inf')))
print(int_1)
replace 0 and/or float('inf') by any numbers you want to evaluate.

Can someone explain this recursive for me?

I get this code from leetcode.
class Solution(object):
def myPow(self, x, n):
if n == 0:
return 1
if n == -1:
return 1 / x
return self.myPow(x * x, n / 2) * ([1, x][n % 2])
This code is used to implement poe(x, n), which means x**n in Python.
I want to know why it can implement pow(x, n).
It looks doesn't make sense...
I understand
if n == 0:
and
if n == -1:
But the core code:
self.myPow(x * x, n / 2) * ([1, x][n % 2])
is really hard to understand.
BTW, this code only works on Python 2.7. If you want to test on Python 3, you should change
myPow(x*x, n / 2) * ([1, x][n % 2])
to
myPow(x*x, n // 2) * ([1, x][n % 2])
The recursive function is to compute power (most probably integer, non negative or -1, power) of a number, as you might have expected (something like x = 2.2 and n = 9).
(And this seems to be written for Python 2.x (due to the n/2 having expected result of integer instead of n//2))
The initial returns are very straight-forward math.
if n == 0:
return 1
if n == -1:
return 1 / x
When the power is 0, then you return 1 and then the power is -1, you return 1/x.
Now the next line consists of two elements:
self.myPow(x * x, n/2)
and
[1, x][n%2]
The first one self.myPow(x * x, n/2) simply means you want to make higher power (not 0 or -1) into half of it by squaring the powered number x
(most probably to speed up the calculation by reducing the number of multiplication needed - imagine if you have case to compute 2^58. By multiplication, you have to multiply the number 58 times. But if you divide it into two every time and solve it recursively, you end up will smaller number of operations).
Example:
x^8 = (x^2)^4 = y^4 #thus you reduce the number of operation you need to perform
Here, you pass x^2 as your next argument in the recursive (that is y) and do it recursively till the power is 0 or -1.
And the next one is you get the modulo of two of the divided power. This is to make up the case for odd case (that is, when the power n is odd).
[1,x][n%2] #is 1 when n is even, is x when n is odd
If n is odd, then by doing n/2, you lose one x in the process. Thus you have to make up by multiplying the self.myPow(x * x, n / 2) with that x. But if your n is not odd (even), you do not lose one x, thus you do not need to multiply the result by x but by 1.
Illustratively:
x^9 = (x^2)^4 * x #take a look the x here
but
x^8 = (x^2)^4 * 1 #take a look the 1 here
Thus, this:
[1, x][n % 2]
is to multiply the previous recursion by either 1 (for even n case) or x (for odd n case) and is equivalent to ternary expression:
1 if n % 2 == 0 else x
This is divide and conquer technique. The implementation above is a fast way of computing exponentiation. At each call, half of the multiplications are eliminated.
Assuming that n is even, x^n can be written as below (If n is odd, it requires one extra multiplication)
x^n = (x^2)^(n/2)
or
x^n = (x^n/2)^2
The function shown above implements the 1st version. It's easy to implement the 2nd one also (I removed recursion base cases below)
r = self.myPow(x,n/2)
return r * r * ([1, x][n % 2])
The right answer might be below
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n > 0:
return self.myPow(x * x, int(n / 2)) * ([1, x][n % 2])
else:
return self.myPow(x * x, int(n / 2)) * ([1, 1/x][n % 2])

What is a subtraction function that is similar to sum() for subtracting items in list?

I am trying to create a calculator, but I am having trouble writing a function that will subtract numbers from a list.
For example:
class Calculator(object):
def __init__(self, args):
self.args = args
def subtract_numbers(self, *args):
return ***here is where I need the subtraction function to be****
For addition, I can simply use return sum(args) to calculate the total but I am unsure of what I can do for subtractions.
from functools import reduce # omit on Python 2
import operator
a = [1,2,3,4]
xsum = reduce(operator.__add__, a) # or operator.add
xdif = reduce(operator.__sub__, a) # or operator.sub
print(xsum, xdif)
## 10 -8
reduce(operator.xxx, list) basically "inserts" the operator in-between list elements.
It depends exactly what you mean. You could simply subtract the sum of the rest of the numbers from the first one, like this:
def diffr(items):
return items[0] - sum(items[1:])
It's tough to tell because in subtraction it's dependent on the order in which you subtract; however if you subtract from left to right, as in the standard order of operations:
x0 - x1 - x2 - x3 - ... - xn = x0 - (x1 + x2 + x3 + ... + xn)
which is the same interpretation as the code snippet defining diffr() above.
It seems like maybe in the context of your calculator, x0 might be your running total, while the args parameter might represent the numbers x1 through xn. In that case you'd simply subtract sum(args) from your running total. Maybe I'm reading too much into your code... I think you get it, huh?
Subtract function is same as sum having negative signs like this
x = 1
y = 2
sum([x, y])
>>> 3
sum([x, -y])
>>> -1
for more numbers
a = 5
b = 10
c = 15
sum([a, b, c])
sum([a, -b, -c])
In general,
Subtract function is formed by changing you list signs like this
l = [1, 2, 3, 4, ...., n]
new_l = l[0] + [-x for x in l[1:]
# Or
new_l = [-x for x in l]
new_l[0] = -newl[0]
# Or one liner,
new_l = [-x for x in l if x != l[0]]

How do i print a table in python?

I am trying to print the output of the following code in two columns using the python launcher:
def main():
print "This program illustrates a chaotic function"
n = input("How many numbers should I print? ")
x = input("Enter a numbers between 0 and 1: ")
y = input("Enter another number between 0 and 1: ")
for i in range(n):
x = 2.0 * x * (1 - x)
print #??
for i in range(n):
y = 2.0 * y * (1 - y)
print #??
main()
for x, y in listOfTwotuples:
print x, y
Given that you've provided no details I've gone ahead and assumed that you've got a list of two-tuples. Update your question with more info and I'll update my answer to match!
edit: with actual details now
If in each loop you store the numbers in a list, you can then use zip to get the format needed to use my code snippet above.
So after reading the input in (be careful with input by the way, using raw_input is better, google why):
xs = []
ys = []
for i in range(n):
xs.append(2.0 * x * (1 - x))
for i in range(n):
ys.append(2.0 * y * (1 - y))
Then you can use zip to apply my code snippet above:
for x, y in zip(xs, ys):
print x, y
zip takes one list [0, 1, 2, ...] and another [10, 20, 30, ...] to produce a list of tuples with these lists [(0, 10), (1, 20), (2, 30), ...].
>>>print "a table in python? using two columns"
a table in python? using two columns
;-)
Check out the format string syntax which will help you to pad strings with spaces to get columns.
If all you want is an x and a y value on each line, then once the preliminaries are done, you can say:
for i in range(n):
x = 2 * x * (1 - x)
y = 2 * y * (1 - y)
print x,y

Categories