Reputation: 1895
i have a function its name is positive_negative
def positive_negative(list_changes):
""" (list of number) -> (number, number) tuple
list_changes contains a list of float numbers. Return a 2-item
tuple where the first item is the sum of the positive numbers in list_changes and
the second is the sum of the negative numbers in list_changes.
>>> positive_negative([0.01, 0.03, -0.02, -0.14, 0, 0, 0.10, -0.01])
(0.14, -0.17)
"""
i can write this function using list techniques as follow :
def positive_negative(list_changes):
pos = sum([item for item in list_changes if item > 0.0])
neg = sum ([item for item in list_changes if item < 0.0])
return pos, neg
and that is a good solution. now my question is how to use the recursion techniques to solve the same function , i have tried the following code , but unfortunately there is something wrong .
def positive_negative(list_changes):
pos = 0.0
neg = 0.0
if len(list_changes)== 0:
pos =+ 0.0
neg =+ 0.0
return pos,neg
else:
if list_changes[0] > 0.0 :
pos =+ list_changes[0]
else:
neg =+ list_changes[0]
positive_negative(list_changes[1:])
return pos,neg
can you help me find what is my mistake and how to get the right recursive function.
thank you
Upvotes: 1
Views: 139
Reputation: 97938
Using some accumulators (psum, nsum):
def positive_negative(list_changes, psum=0, nsum=0):
if len(list_changes) == 0:
return psum, nsum
if list_changes[0] < 0:
nsum += list_changes[0]
else:
psum += list_changes[0]
return positive_negative(list_changes[1:], psum, nsum)
# and another version:
def positive_negative2(list_changes, psum=0, nsum=0):
if len(list_changes) == 0:
return psum, nsum
if list_changes[0] < 0:
return positive_negative(list_changes[1:],
psum, nsum + list_changes[0])
return positive_negative(list_changes[1:],
psum + list_changes[0], nsum)
print positive_negative([0.01, 0.03, -0.02, -0.14, 0, 0, 0.10, -0.01])
Output
(0.14, -0.17)
As a side note, python does not do tail call optimization so be cautious when using recursion. The function above fails if your list has about 1000 items in it.
Upvotes: 2
Reputation: 7491
not using tail recursion:
import operator
def positive_negative_change(l):
if not l:
return (0.0, 0.0)
if l[0] >= 0:
return tuple(map(operator.add, (l[0], 0.0),
positive_negative_change(l[1:])))
else:
return tuple(map(operator.add, (0.0, l[0]),
positive_negative_change(l[1:])))
in python one would use a generator, or tail recursion... if you are into brushing up recursion just read the little schemer
Upvotes: 2
Reputation: 365657
Your first problem is this:
pos =+ list_changes[0]
Python doesn't have an =+
operator. So, this is equivalent to:
pos = (+list_changes[0])
Since list_changes[0]
is a number, and +n
is the same as n
for any number (except in certain edge cases which don't matter here), you're just replacing pos
each time instead of adding to it.
You probably want this:
pos += list_changes[0]
But the fact that you're trying to use +=
at all is a more fundamental misunderstanding. Each instance of positive_negative
on the stack has its own pos
and neg
values. These start at 0.0, then you add either 0.0
or list_changes[0]
to them, then you call a function that doesn't affect them, then you return them. So, you're going to end up returning either 0.0, list_changes[0]
or list_changes[0], 0.0
; whatever comes later in the list will never affect the result.
If you want the recursive function call to add anything, you need to do something with its return value. Something like this:
def positive_negative(list_changes):
if len(list_changes)== 0:
return 0.0, 0.0
else:
pos, neg = positive_negative(list_changes[1:])
if list_changes[0] > 0.0:
pos += list_changes[0]
else:
neg += list_changes[0]
return pos, neg
Of course this solution obviously isn't tail-recursive… but that doesn't matter, because Python doesn't do tail recursion optimization anyway. I think this is the closest solution to what you were trying to accomplish.
Upvotes: 2