Even and Odd numbers with recursion in Python - python

I'm trying to solve "is_even" and "is_odd" function in terms of the other with recursion. I don't understand HOW this function as written ever evaluates to False, or how anything that isn't 0 ever evaluates to True. I double-checked it in teamtreehouse.com workspaces to make sure it works at all, but I can't figure out HOW it works.
I understand that it's decrementing through recursion, but I don't understand how is_odd(x) works. If is_odd(x) just negates everything in is_even, why don't all numbers evaluate to True? Or False?
def is_even(x):
if x == 0:
return True
else:
return is_odd(x-1)
def is_odd(x):
return not is_even(x)
# Does this negate the function of is_even(x)?
# Does that negating mean returning False, or sending to else block?
# If the negating does automatically sends to the else block
# After we get here, do we ever land at True in is_even(x)?
# If not, how do we ever land at False?
print(is_even(1))
print(is_even(2))
print(is_even(3))

x = 0
is_even: True
x = 1
is_even:
is_odd(0):
is_even(0): True
not True: False
False
x = 2
is_even:
is_odd(1):
is_even(1): False
not False: True
True
x = 3
is_even:
is_odd(2):
is_even(2): True
not True: False
False

Let's take an example of the function is_even(1). What happens?
(1)
Enter in is_even(1)
Enter in is_odd(1-1), i.e. enter in is_odd(0)
Return not is_even(0). Enter in is_even(0)
x==0 -> this returns True
You have a not, remember in Step 3? So: not True -> False
is_even(1) = False
Let's now take an example of is_even(2). What happens?
(2)
Enter in is_even(2)
Enter in is_odd(2-1), i.e. enter in is_odd(1)
return not is_even(1)
We know from (1) that is_even(1) is False, so not False = True
Now with is_even(3)
(3)
Enter in is_even(3)
Enter in is_odd(3-1), i.e. enter in is_odd(2)
return not is_even(2)
We knot from (2) that is_even(2) is True, so not True = False
To your questions again:
Does this negate the function of is_even(x)?
Yes: not is_even(x) negates the result of is_even(x), as you saw in my examples.
Does that negating mean returning False, or sending to else block?
No. If the function is_even(x) returns True, not True returns False.
If the function is_even(x) returns False, not False returns True. So it negates the result of is_even(x)
After we get here, do we ever land at True in is_even(x)?
Since you always decrease the argument with (x-1), you will always eventually get to x=0, as you also saw in my examples.

What Sasha said is correct, however it does not fully illustrate the recursive call-stack.
x = 3
is_even(3):
return is_odd(2)
call is_even(2)
return is_odd(1)
call is_even(1)
return is_odd(0)
return is_even(0): True
return not True: False
return not False: True
return not True: False

Related

how does this code work its printing false ? where did i make mistake?

def check_22(num_list):
for i in range(0, len(num_list)-1):
if num_list[i] == 2 and num_list[i+1] == 2:
return True
else:
return False
print(check_22([3,2,5,1,2,1,2,2]))
How come the output is False when it needs to display True?
What your code does right now is as soon as it gets in checks 3 and 2, they are not both 2 so it returns false. What you want for your purpose is:
for i in range(0,len(num_list)-1):
if num_list[i]==2 and num_list[i+1]==2:
return True
return False
So it would return false only after checking the whole list and not finding 2 successive 2s.
Do not return False unless you are done the whole loop
def check_22(num_list):
for i in range(0, len(num_list)-1):
if num_list[i] == 2 and num_list[i+1] == 2:
return True
return False
first of all indentation is important in python:
def check_22(num_list):
#start writing your code here
for i in range(0,len(num_list)-1):
if num_list[i]==2 and num_list[i+1]==2:
return True
else:
return False
At the beginning, the index i is zero, and thus it checks the first and the second items,they are 3 and 2, thus the test is false, and it returns false. that's all. It ends at the very beginning, That's why the answer is false and not true, it will never check the last two 2s.

Error when using a variable in recursion to iterate through a binary tree (Python)

def berry_finder(t):
"""Returns True if t contains a node with the value 'berry' and
False otherwise.
>>> scrat = tree('berry')
>>> berry_finder(scrat)
True
>>> sproul = tree('roots', [tree('branch1', [tree('leaf'), tree('berry')]), tree('branch2')])
>>> berry_finder(sproul)
True
"""
if is_leaf(t):
if label(t)=='berry':
return True
else :
return False
else:
if label(t)=='berry':
return True
else:
branch_list=[]
for branch in branches(t):
branch_list+=[berry_finder(branch)]
if True in branch_list:
return True
else:
return False
The code doesn't work.And the function's purpose is to find if any node's value is 'berry'.
The wrong part of the code is the recursion part(i.e. the code under the second else)
I wonder whethet it is the problem of the usage of branch_list,because the branch_list may change during the recursion?
The problem is that you reset branch_list in each iteration of the loop, so losing the previous boolean results, and ending up with only the last result.
You need to move that out of the loop, like so (but read on to reduce the code further -- step by step):
branch_list=[]
for branch in branches(t):
branch_list+=[berry_finder(branch)]
Not a problem, but it is more natural to use append here:
branch_list=[]
for branch in branches(t):
branch_list.append(berry_finder(branch))
And more pythonic is to build the list in one go through map:
branch_list = list(map(berry_finder, branches(t)))
or comprehension:
branch_list = [berry_finder(branch) for branch in branches(t)]
But you don't actually need to collect the booleans in a list at all. Just use any:
return any(map(berry_finder, branches(t)))
The whole function can be reduced to just this:
def berry_finder(t):
return label(t)=='berry' or any(map(berry_finder, branches(t)))
You alread get answer how to use it with list
... but you don't need list for this because you can return True directly when berry_finder(branch) gives first True, and you can return False when you exit loop.
else:
for branch in branches(t):
if berry_finder(branch): #
return True
# --- after loop ---
return False
BTW:
Instead of
if True in branch_list:
return True
else:
return False
you can use shorter
return (True in branch_list) # you can even skip `()`
because ... in ... gives True or False
Similar
return (label(t) == 'berry') # you can even skip `()`
And you would replace results
if True in branch_list:
return False
else:
return True
you can use shorter
return not (True in branch_list)
or
return (True not in branch_list)
but it is not the same as return (False in branch_list)

Why does this function return "None" if the number isn't even? How can I make it return "False" without using an else condition?

def my_function(n):
if(n % 2 == 0):
return True
print(my_function(2))
print(my_function(5))
Output:
True
None
I understand that 'False' has to be explicitly specified to be returned by the function but don't exactly understand why.Can this function be made to return false without an else loop incorporated?
def my_function(n):
if(n % 2 == 0):
return True
return False
Since it is only one return indication, otherwise it returns none, 'nothing'. Here we have forced it to return False otherwise.
1st question: If you did not specify any return in a Python function, it will return none.
2nd question: You can do return n%2 == 0, which will return true if n is even number and false if n is odd number.
To answer your question: you are trying to get a False value out of something that doesn't have a value at all. Therefore it is 'none'. Just because it isn't true doesn't necessarily mean it's false.
There are two common ways to go about doing this though:
def my_function(n):
return n % 2 == 0
This will evaluate to either True or False depending on the parameter n and then it will return the value.
The other way:
def my_function(n):
if(n % 2 == 0):
return True
return False
Here, if we pass the if check, the function will return True and it will never make it to the return False statement. Vice versa, if we don't pass the if check we will instead return False. I prefer to write code this way because it's a little more specific in what the code is doing. Either way works though

Trying to make a function that when you input a string of numbers it returns true if the length of the numbers is 4 or 6 and they are all numbers

def validate_pin(pin):
if (len(pin) == 4 or 6) and pin.isalnum == True:
return True
else:
return False
It works for some but numbers like "1234" are returned as "false" even though it should be True
You have some syntax errors:
you need to provide the left hand side operator for each comparison in your if statement
isalnum is a function, so it needs to be called. You were checking whether the function itself is type bool of value True, which evaluates to false since the function isalnum is a built in method.
def validate_pin(pin):
if (len(pin) == 4 or len(pin) == 6) and pin.isalnum() == True:
return True
else:
return False
Note that you don't need to have == True in the isalnum() comparison, since the function already returns a boolean object:
def validate_pin(pin):
if (len(pin) == 4 or len(pin) == 6) and pin.isalnum():
return True
else:
return False
A few things:
len(pin) == 4 or 6
this is evaluated as (len(pin) == 4) or (6 is truthy). All numbers other than 0 are truthy, so that second half is a problem. This should instead be
len(pin) == 4 or len(pin) == 6
pin.isalnum
pin.isalnum is a function, aka a bunch of instructions that the computer understands, and a bunch of instructions is never equal to True. You have to actually tell python to call (execute) the function to see if the instructions return true or false. You call a function by putting parentheses after it:
>>> "123".isalnum()
True
>>> "123".isalnum
<built-in method isalnum of str object at 0x108064ce0>
>>>
Also, you don't need to check if it's equal to true - pin.isalnum() will be evaluated, and then whatever the answer is, it gets put in that place. So you can just say ... and pin.isalnum(), no need to check if the result is true or not.
Putting it together, your statement should be
if (len(pin) == 4 or len(pin) == 6) and pin.isalnum():
return True
I'd use regex something like ^\d{6}$|^\d{4}$
or this ^\d{4}(\d{2})?$
https://regex101.com/r/AFksCd/1

Why does Python evaluate strings/numbers as True in if statements yet myNumber == True returns False?

The following will print 'ok':
if 5:
print('ok')
Yet when I do:
print(5 == True)
The output is False.
The same thing happens with strings. Why?
You're testing different things here.
The if just checks if the bool of the expression (see also "Truth value testing") is True not if the identity is equal to True.
So what is actually tested by the if is:
>>> bool(5) == True
True
True has value 1. If you set True = 5 (only in python 2) the equality become True. The 'if' statement is like it is checking if the guard is not 0 or None so every number not 0 is ok to enter in the first block. In fact False has value 0.

Categories

Resources