How to get a single output from a function with multiple outputs? - python

I have the following simple function:
def divide(x, y):
quotient = x/y
remainder = x % y
return quotient, remainder
x = divide(22, 7)
If I accesss the variable x I get:
x
Out[139]: (3, 1)
Is there a way to get only the quotient or the remainder?

You are essentially returning a tuple, which is an iterable we can index, so in the example above:
print x[0] would return the quotient and
print x[1] would return the remainder

You have two broad options, either:
Modify the function to return either or both as appropriate, for example:
def divide(x, y, output=(True, True)):
quot, rem = x // y, x % y
if all(output):
return quot, rem
elif output[0]:
return quot
return rem
quot = divide(x, y, (True, False))
Leave the function as it is, but explicitly ignore one or the other of the returned values:
quot, _ = divide(x, y) # assign one to _, which means ignore by convention
rem = divide(x, y)[1] # select one by index
I would strongly recommend one of the latter formulations; it's much simpler!

You can either unpack the return values when you call your method:
x, y = divide(22, 7)
Or you can just grab the first returned value:
x = divide(22, 7)[0]

Related

Return second smallest number in a nested list using recursion

I have to return the second smallest number in a python list using recursion, and no loops. What I have done is created a helper function that returns a tuple of the (smallest, second smallest) values in the list, and then I just take the tuple[1] in my second_smallest func.
def s_smallest(L):
if(len(L) == 2):
if (L[0] >= L[1]):
return (L[1],L[0])
else:
return (L[0],L[1])
else:
first_smallest,second_smallest = s_smallest(L[1:])
if L[0] >= first_smallest and L[0] <= second_smallest:
return (first_smallest, L[0])
elif L[0] <= first_smallest:
return (L[0], first_smallest)
else:
return (first_smallest, second_smallest)
This works, but now I need to handle nested lists, so s_smallest([1,2,[3,0]]) should return (0,1). I tried doing this:
if isinstance(L[0],list):
first_smallest,second_smallest = s_smallest(L[0])
else:
first_smallest,second_smallest = s_smallest(L[1:])
to get the first smallest and second smallest values if it is a list, but I get an error saying builtins.TypeError: unorderable types: int() >= list(). How can I fix this problem to deal with nested lists?
I might suggest separating the list unnesting and the min reducing into two separate, well-defined tasks
deepReduce will reduce a list of lists using the specified reducing function
deepMin performs a deepReduce using min
import math # used for math.inf
def min (x,y):
return x if x < y else y
def deepReduce (f, y, xs):
if not xs:
return y
elif isinstance(xs[0], list):
return deepReduce(f, deepReduce(f, y, xs[0]), xs[1:])
else:
return deepReduce(f, f(y, xs[0]), xs[1:])
def deepMin (xs):
return deepReduce (min, math.inf, xs)
data = [1,2,[7,[6,1,3,[0,4,3]],3,4],2,1]
print(deepMin(data))
# 0
Oh, but you said you want the second smallest number. Let's rework that code a little bit. Of course I knew that all along, but answering this question twice allows me to demonstrate the versatility of this specific implementation – Changes in bold
def min2 (xs, y):
# x1 is the smallest, x2 is second smallest
x1, x2 = xs
if (y < x1) and (y < x2):
return (y, x2)
elif y < x2:
return (x1, y)
else:
return (x1, x2)
def deepMin2 (xs):
# notice we change to use tuple of math.inf now
x1, x2 = deepReduce (min2, (math.inf, math.inf), xs)
return x2
data = [1,2,[7,[6,1,3,[0,4,3]],3,4],2,1]
print(deepMin2(data))
# 1
I should point out that we didn't have to touch deepReduce at all, which is the point – we should be able to do any arbitrary deep operation on our nested list without having to statically code that behaviour into our function.
Now you can write whatever deep reducer you want and call it with deepReduce
Full solution
Using nothing but functools.reduce, no loops, to handle lists of arbitrary nesting:
import functools
def helper(acc, x):
if type(x) is list:
return functools.reduce(lambda acc, x: helper(acc, x), x, acc)
else:
if x < acc[0]:
return (x, acc[0])
elif x < acc[1]:
return (acc[0], x)
else:
return (acc[0], acc[1])
def second_smallest(l):
if len(l) < 2:
return None
else:
if l[0] <= l[1]:
return functools.reduce(lambda acc, x: helper(acc, x), l[2:], (l[0], l[1]))
else:
return functools.reduce(lambda acc, x: helper(acc, x), l[2:], (l[1], l[0]))
>>> second_smallest([1,2,[0,3,[-1,-2]]])
(-2, -1)

How to put numbers in ascending, return them in a tuple, and add another argument.(Python)

Function signature :
def rank3(x,y,z, ascending=True)
Given three integers, return them in order in a tuple of
length three. An optional fourth argument (ascending) states whether output should be sorted ascending (argument is True) or descending (argument is False).
Examples:
§ rank3(5, 3, 4) → (3,4,5)
§ rank3(5, 3, 4, False) → (5,4,3)
§ rank3(6, 8, 6) → (6,6,8)
This is my code so far:
x = num1 #your first input
y = num2 #your second input
z = num3 #your third input
a = [x, y, z] #your list of inputs
b = [] #your sorted list
def rank3(x,y,z, ascending=True):
while a: # your sort function
o = a[0]
for i in a:
if i < o:
o = i
b.append(o)
a.remove(o)
return b #return your final answer
Try with
import bisect
def rank3(x,y,z, ascending=True):
if x <= y:
ret = [x, y]
else:
ret = [y, x]
pz = bisect.bisect(ret, z)
ret.insert(pz, z)
if not ascending:
ret = ret[::-1] # or use ret.reverse()
return tuple(ret)
In case you do not even want to use bisect, do a little while loop until you find an element in ret which is greater than z (hint, use enumerate)
However, this is shorter and more pythonic
def rank3(x,y,z, ascending=True):
return tuple(sorted((x,y,z), reverse=not ascending))
First of all - try to find answer in built-in python functions.
And after all write your own.
For your example python have a good method sorted(). And you can reverse your list/tuple by reverse() method.

find the domain of a function, given the root of it

I need help writing a method that receives a function, and some number y and returns x such that f(x) = y. The function is differentiable using Newton's method:
from random import *
def diff_param(f,h=0.001):
return (lambda x: (f(x+h)-f(x))/h)
def NR(func, deriv, epsilon=10**(-8), n=100, x0=None):
""" returns a number such that f(number) == 0"""
if x0 is None:
x0 = uniform(-100.,100.)
x=x0; y=func(x)
for i in range(n):
if abs(y)<epsilon:
#print (x,y,"convergence in",i, "iterations")
return x
elif abs(deriv(x))<epsilon:
#print ("zero derivative, x0=",x0," i=",i, " xi=", x)
return None
else:
#print(x,y)
x = x- func(x)/deriv(x)
y = func(x)
#print("no convergence, x0=",x0," i=",i, " xi=", x)
return None
I need to write a method source(f,y) that returns the x such that f(x) = y.
def source(f,y):
You need to find the zeros of g(x) = f(x)-y :
def source(f,y):
def g(x):
return f(x)-y
x = NR(g, diff_param(g))
return x
This returns a single x, but there may be others. To find them you need to try other initial values x0.

sum variable in a range (python)

This was the question:
Write a function called sum_range that accepts 2 integer values as
parameters and returns the sum of all the integers between the two
values, including the first and last values. The parameters may be in
any order (i.e. the second parameter may be smaller than the first).
For example:
result = sum_range(1, 1)
print(result) 1
result = sum_range(2, 4) print(result) 9
result = sum_range(3, 2)
print(result) 5
my codes are as below, I dont know where it went wrong
but when I test the codes, it returned 'none' when (2,4) (3,2) were entered
def sum_range(x,y):
if x == y:
return x
if x<y:
sum(range(x,y))
return
if x>y:
sum(range(y,x))
return
You could do better (at least I think), here is my code for that:
def sum_range(a, b):
return sum(range(min(a,b),max(a,b)+1))
You were very close but forgot to return the actual value from the calculations. If you just type "return", you will return None and not the result from the sum.
You also did not include the last number in the range in the sum. See corrected code below:
def sum_range(x, y):
if x == y:
return x
if x < y:
return sum(range(x, y+1))
if x > y:
return sum(range(y, x+1))
You need to return the sum which you are not doing in the x<y and x>y cases. You should
return sum(range(x,y)) or return sum(range(y,x)) as appropriate.
Note also that there is a bug in your range() expressions - "including the first and last values". Hint: What does range(1,3) output?
def sum_range(x,y):
if x == y:
return x
elif x < y:
s = 0
for i in range(x,y):
s += x+(x+1)
return s
elif x > y:
s = 0
for i in range(y,x):
s += y+(y+1)
return s
This is done without using sum() function.

Repeat function python

I'm stuck at higher-order functions in python. I need to write a repeat function repeat that applies the function f n times on a given argument x.
For example, repeat(f, 3, x) is f(f(f(x))).
This is what I have:
def repeat(f,n,x):
if n==0:
return f(x)
else:
return repeat(f,n-1,x)
When I try to assert the following line:
plus = lambda x,y: repeat(lambda z:z+1,x,y)
assert plus(2,2) == 4
It gives me an AssertionError. I read about How to repeat a function n times but I need to have it done in this way and I can't figure it out...
You have two problems:
You are recursing the wrong number of times (if n == 1, the function should be called once); and
You aren't calling f on the returned value from the recursive call, so the function is only ever applied once.
Try:
def repeat(f, n, x):
if n == 1: # note 1, not 0
return f(x)
else:
return f(repeat(f, n-1, x)) # call f with returned value
or, alternatively:
def repeat(f, n, x):
if n == 0:
return x # note x, not f(x)
else:
return f(repeat(f, n-1, x)) # call f with returned value
(thanks to #Kevin for the latter, which supports n == 0).
Example:
>>> repeat(lambda z: z + 1, 2, 2)
4
>>> assert repeat(lambda z: z * 2, 4, 3) == 3 * 2 * 2 * 2 * 2
>>>
You've got a very simple error there, in the else block you are just passing x along without doing anything to it. Also you are applying x when n == 0, don't do that.
def repeat(f,n,x):
"""
>>> repeat(lambda x: x+1, 2, 0)
2
"""
return repeat(f, n-1, f(x)) if n > 0 else x

Categories

Resources