I have a code that checks if a given list of integers can sum up to a specified target. If any combination of the integers in a list can sum up to a target value, it returns True. The input 'start' is the index of the list that I want to start from and continue until the end of the list
def groupSum(start, nums, target):
if start >= len(nums):
return target == 0
else:
return groupSum(start + 1, nums, target - nums[start]) or groupSum(start + 1, nums, target);
So, if I put
groupSum(0, [2,4,8], 10)
it will return True, and, if I put
groupSum(0, [2,4,8], 9)
it will return False
QUESTION: I don't understand how they can put 'or' in the return statements, in a recursive case. I don't see how that's actually working. Is it passing multiple functions simultaneously to check every combination or what?
I'm pretty new to Recursion method and would appreciate it if you can explain the technique used here. Thanks
In python and and or operators, do not return boolean values. They return the last thing evaluated. So, when you
return a or b
if a is a truthy value, a will be returned. Otherwise, the truthness of the expression depends on b, and so b will be returned.
Why it's True for 10 is because there's an exact match for 10 (8+2); which your recursive function reduces to 0 for the target variable.
So, groupSum(start + 1, nums, target - nums[start]) this becomes True - so the comparison will be True or False, which will turn out to True!
Now, for the value of 9, there's no such match and hence it'll always remain False.
You can try for 12 and 6 as well. It'll return True.
Whereas, for any other value the comparison will always be False or False.
Related
Code
def addition(num):
if num:
return num + addition(num - 1)
else:
return 0
res = addition(10)
print(res)
Explanation
I know what the function is doing:
it is a recursive function
I just don't know what if num: means or the else part.
I am guessing it means as long as the num is int do what is inside the if, else return 0.
Question
Can someone tell me what this code means?
if variable: and truthyiness
See the boolean values and Python's Truth Value Testing:
What is Truthy and Falsy? How is it different from True and False?
You can evaluate truthy and falsy values using the bool() conversion-function:
print('None:', bool(None))
print('zero:', bool(0))
print('negative:', bool(-1))
print('positive:', bool(1))
if num: mets if num is defined and unequal to 0:
is defined: num is not None
and is not zero: num != 0
bool(0) is False. The opposite condition is tested by if not num.
The role of if in a recursive function
It's a recursive function which calls itself until exit-condition num == 0 is met in the else branch. Then it simply returns 0. So, the role of if num: is the continue-condition opposed to an exit-condition.
You could also write it as exit-condition:
def addition(num):
if not num: # equivalent to: if num == 0 or num is None
return 0 # return 0 if exit-condition met
# default behavior: recurse until zero met
return num + addition(num - 1)
See also:
recursive factorial function
Basics of recursion in Python
Edge-cases for input
Note, how input of None and other falsy values return a zero.
Please also consider the edge-case of negative input, as Fred commented. Could (silently) return 0 to abort addition. Also might raise an error to warn about misuse, like:
if num < 0:
raise ValueError("Can not calculate the recursive-sum for negative values.")
What happens if a float like 10.5 is given as input?
It would step through each -1 decrease until 0.5. The next call of addition(-0.5) would jump over the num == 0 exit-condition and cause infinite recursion, even a stackoverflow.
Python and many other languages have a concept of "falsy", which roughly means "values that are treated as False when evaluated as a boolean". In Python, values that are falsy include empty collections such as empty lists, strings, sets, tuples, and dicts, the int or float 0, and None. I may be missing some here, and you may find that some classes are designed to be treated as falsy as well under certain conditions. There are also "truthy" values which evaluate to True is a boolean context. It's easy to find out if a value is truthy or falsy. Simply call bool() on it:
bool(0.0)
# False
In the context of your code, when 0 is reached, that will be evaluated as falsy, triggering the exit condition.
if num: means if num is different than 0 : if num!=0.
you better remove the else statement.
def addition(num): if num: return num + addition(num - 1) return 0
python already knows that return is an else statement.
here's a playlist of one of the bests on youtube by corey to learn & become at python : https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7
and also I recommend this book, automating the boring stuff with python. it's free : https://automatetheboringstuff.com/
def greater(list, num)
for x in list:
if x > num:
return True
else:
return False
as you can see in my code, i am trying to write a function that return True if list_number contained number that is bigger than second argument, otherwise return False.
but here is confusing:
when i input: greater([1, 2, 3], 2), and its return False. I am wondering why is that? the first argument contained 3 and its bigger than 2.
any helps and explanations will be appreciated.
You want to have it return at the end of the function. Right now, you have it return after checking only the first number. Try this:
def has_gt(list_number,number):
for x in list_number:
if x > number:
return True
return False
A property of if/else is that if one runs, the other doesn't. But in both cases, one runs. In your code, this snippet:
if x > number:
return True
else:
return False
Means that it will check if the number is bigger than the number in question. If it is, it will return True. If not, it will return False. A return call instantly ends the processing of a function, so it will stop checking after that.
To summarize, your code loops through the target list. It checks the first number, one, and sees if it is bigger than two. It is not, so the code returns False, instantly ending the function. So, your function just ended in a False, which is what it returned.
The change I made was that it returns False at the end of the code. This means that it will check each value for being greater than the target. If it finds any value greater than the target, it will end processing, with a return value of True. If the code hasn't returned by the time it reaches the end of the function, it will return False because of the statement at the end of the function.
Actually what happens is the else part also runs just after comparing the number (here 2) with the first element in the list_number (here 1) thus returns false.
So the solution is you need to let the for loop first run completely which is stopped by the else statement.
def has_gt(list_number,number):
for x in list_number:
if x > number:
return True
return False
I'm new to python and was looking around for a code for a function where the user inputs and integer and the function adds and returns the sum of the digits of the number.
The code looked like this:
def sum_digits(n):
s = 0
while n:
s += n % 10
n //= 10
return s
So I know how a while loop works, but I can't wrap my head around (nor am able to find anything on Google) about how this works. I thought While loops always have a condition such as 'while n<10' or the sort.
What exactly is 'while n:' saying? How does this code work exactly? How does the code know how to stop running, and how exactly does it even return the sum of the digits (all I see it doing is returning the remainder of s/n).
Thanks for the help and sorry for any stupid questions.
while implicitly calls bool on the argument. So as long as bool(n) in your example is True the while loop continues.
And Pythons documentation for builtin types states that any number except zero is considered True:
By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object. Here are most of the built-in objects considered false:
constants defined to be false: None and False.
zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
empty sequences and collections: '', (), [], {}, set(), range(0)
So basically the while n loop will continue until n becomes zero (or you break or return or raise...)
while n: is equivalent to while n!=0: (in this case, when you're dealing with numbers). Since each value in python has a Boolean value, for any number that is different from zero, bool(n) == True, if n equals zero, bool(n) == False.
That function can be written like (Thanks to #Jean-FrançoisFabre for suggesting the use of divmod):
def sum_digits(n):
s = 0
while n != 0:
n, t = divmod(n, 10) # to not use division and modulo separately
# n has the value of n//10, t has the value of n%10
s += t
return s
print(sum_digits(154)) # => 10
print(sum_digits(134)) # => 8
print(sum_digits(987)) # => 24
I feel very confused about some code like this[not written by me]:
version = any(func1(), func2()) # wrong, should be any([func1(), func2()])
def func1():
if something:
return 1
else:
return None
def func2():
if something:
return 2
else:
return 3
version must be a num. when [func1(), func2()] is [1, None], should return 1, when is [None, 2], should return 2, when [1, 2], should return 1.
so I think it's wrong to use any() in this code, because any() just return True or False. If I rewirte this logic using another way, I can not find a graceful way as a pythoner.
I want to know whether any() can achieve the logic, if not, how to achieve it gracefully?
You can simply use or here.
version = func1() or func2()
Make sure the functions are defined before trying to call them.
This works because or returns the first True-like value or the last value (if no value is True-like) . And 'None' is considered False-like in Boolean context.
#AnandSKumar's answer is optimal. But just to give you some information on any if you are interested:
Take this example:
>>> def foo():
... return 2
...
>>> def boo():
... return 3
...
>>> def doo():
... return 4
...
>>> f = [foo, boo, doo]
>>> any(i() < 3 for i in f)
True
Ultimately what is happening inside the any is, iterate over the array of methods j, and indicate whether each item is less than 3, what the "any" will do in this case is return "ANY" condition that matches that. So even if you find one that is False, it will still return True.
There is another similar method to this called "all", that will ensure that ALL conditions are met based on your condition you are checking. Here is the example:
>>> all(i() < 3 for i in f)
False
So, as you can see, because one condition failed, it will return False.
For the arbitrary length case (where explicitly chaining or doesn't make sense), you can make a version of any that returns the first truthy value or a given value when all results are falsy with:
# If on Py2, you'll want to do this to get shortcircuiting behavior
from future_builtins import filter
result = next(filter(None, iterable_to_check), False) # False can be replaced with a chosen default
The filter only produces "truthy" values, and the two arg next gets the first "truthy" value, or the default value if filter finds no "truthy" values.
If the iterable_to_check is a non-empty Sequence (rather than merely Iterable), you can exactly match the behavior of chained ors (the "falsy" result is the last value, not a specific value like False or None) with:
result = next(filter(None, sequence_to_check), sequence_to_check[-1])
to use the final element ("truthy" or "falsy") as the result when all elements were "falsy".
To be clear, if the set of things to test is fixed and smallish, explicit or per Anand's answer is the better way to go.
I have always thought that using -1 in a condition is alway the same as the writing False (boolean value). But from my code, I get different results:
Using True and False:
def count(sub, s):
count = 0
index = 0
while True:
if string.find(s, sub, index) != False:
count += 1
index = string.find(s, sub, index) + 1
else:
return count
print count('nana', 'banana')
Result: Takes to long for interpreter to respond.
Using 1 and -1:
def count(sub, s):
count = 0
index = 0
while 1:
if string.find(s, sub, index) != -1:
count += 1
index = string.find(s, sub, index) + 1
else:
return count
print count('nana', 'banana')
Result: 1
Why does using -1 and 1 give me the correct result whereas using the bool values True and False do not?
string.find doesn't return a boolean so string.find('banana', 'nana', index) will NEVER return 0 (False) regardless of the value of index.
>>> import string
>>> help(string.find)
Help on function find in module string:
find(s, *args)
find(s, sub [, start [, end]]) -> int
Return the lowest index in s where substring sub is found,
such that sub is contained within s[start,end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
>>>
Your example simply repeats:
index = string.find('banana', 'nana', 0) + 1 # index = 3
index = string.find('banana', 'nana', 3) + 1 # index = 0
The -1 version works because it correctly interprets the return value of string.find!
False is of type bool, which is a sub-type of int, and its value is 0.
In Python, False is similar to using 0, not -1
There's a difference between equality and converting to a boolean value for truth testing, for both historical and flexibility reasons:
>>> True == 1
True
>>> True == -1
False
>>> bool(-1)
True
>>> False == 0
True
>>> bool(0)
False
>>> True == 2
False
>>> bool(2)
True
I have always thought that using -1 in a condition is alway the same as the writing False (boolean value).
1) No. It is never the same, and I can't imagine why you would have ever thought this, let alone always thought it. Unless for some reason you had only ever used if with string.find or something.
2) You shouldn't be using the string module in the first place. Quoting directly from the documentation:
DESCRIPTION
Warning: most of the code you see here isn't normally used nowadays.
Beginning with Python 1.6, many of these functions are implemented as
methods on the standard string object. They used to be implemented by
a built-in module called strop, but strop is now obsolete itself.
So instead of string.find('foobar', 'foo'), we use the .find method of the str class itself (the class that 'foobar' and 'foo' belong to); and since we have objects of that class, we can make bound method calls, thus: 'foobar'.find('foo').
3) The .find method of strings returns a number that tells you where the substring was found, if it was found. If the substring wasn't found, it returns -1. It cannot return 0 in this case, because that would mean "was found at the beginning".
4) False will compare equal to 0. It is worth noting that Python actually implements its bool type as a subclass of int.
5) No matter what language you are using, you should not compare to boolean literals. x == False or equivalent is, quite simply, not the right thing to write. It gains you nothing in terms of clarity, and creates opportunities to make mistakes.
You would never, ever say "If it is true that it is raining, I will need an umbrella" in English, even though that is grammatically correct. There is no point; it is not more polite nor more clear than the obvious "If it is raining, I will need an umbrella".
If you want to use a value as a boolean, then use it as a boolean. If you want to use the result of a comparison (i.e. "is the value equal to -1 or not?"), then perform the comparison.