If and elif question: which one is valid? - python

So I have this two scripts with same content, but different if statements inside the loop:
Based on my understanding and if, if tests both conditions while if, elif testes up to the first condition that is True and ignores the next ones.
Why my instructor tells me that if, elif is the right answer? shouldn't both of them be valid answers?
def has_letter_cases(s: str) -> bool:
"""Return True if and only if s contains at least one lowercase letter
and an uppercase letter
>>>has_letter_cases('abcABC')
True
>>>has_letter_cases('abc123')
False
>>>has_letter_cases('ABCXYZ')
False
"""
upper = False
lower = False
for ch in s:
if ch.islower():
lower = True
if ch.isupper():
upper = True
return bool(upper and lower)
def has_letter_cases(s: str) -> bool:
"""Return True if and only if s contains at least one lowercase letter
and an uppercase letter
>>>has_letter_cases('abcABC')
True
>>>has_letter_cases('abc123')
False
>>>has_letter_cases('ABCXYZ')
False
"""
upper = False
lower = False
for ch in s:
if ch.islower():
lower = True
elif ch.isupper():
upper = True
return bool(upper and lower)

Related

What's wrong with recursive Regex function code in python

I wrote a regex code which compares two strings. It recognises a special character '?' that allows zero or more instances of previous character. It works fine until there are two or more occasions of '?' in the string. And I can't make out why.
def single_character_string(a, b) -> "return True if characters match":
"""check if two characters match"""
if len(a) == 0:
return True
elif len(b) == 0:
return False
else:
if a == '.':
return True
else:
if a == b:
return True
else:
return False
def meta_question_result(temp):
if len(temp) >= 2:
if temp[1] == '?':
k_1 = temp.replace(temp[0: 2], '') # no char
k_2 = temp.replace(temp[1], '') # char
return k_1, k_2
def check_pair_by_pair(template, check_string) -> "Strings are of Equal length! " \
"return True if lines are identical":
"""check if two strings match symbol by symbol. template may be less than string, the opposite
is False"""
if not template: # exit from recursion
return True
if not check_string: # exit from recursion
return False
if meta_question_result(template):
t_1, t_2 = meta_question_result(template)
if single_character_string(t_1[0], check_string[0]):
return check_pair_by_pair(t_1[1:], check_string[1:])
if single_character_string(t_2[0], check_string[0]):
return check_pair_by_pair(t_2[1:], check_string[1:])
else:
return False
elif single_character_string(template[0], check_string[0]):
return check_pair_by_pair(template[1:], check_string[1:])
else:
return False
reg, st = input().split("|")
print(check_pair_by_pair(reg, st))
reg = "co?lou?r"
st = "colour"
gives True as expected,
reg = "co?lou?r"
st = "clor"
gives True as expected,
but...
reg = "co?lou?r"
st = "color"
gives False. I expected True.
Found the bag.
Replace method replaces all instances of '?'. So the second '?' was replaced also and program didn't see it.
I should add an argument 'count' to replace method that is equal to 1.
k_1 = temp.replace(temp[0: 2], '', 1) # no char

Why does one part of conditional statements in Python returns None while others are ok?

I need to write a code that prints out valid or invalid for an input of letters and numbers for a license plate. The conditions are: first two characters must be letters, characters have to be between 2 and 6, and if numbers are used, 0 should not be the first, nor should a number appear before a letter.
I put the code below on Thonny and cannot understand why len(l) == 4 part of the conditional statement for def valid_order() returns None and does not execute the next line of the code whereas others work fine. My code should return "Valid" for CSAA50, but it returns invalid. Why?
Also, is there an elegant way to write def valid_order()?
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
if s[0:2].isalpha() and 6 >= len(s) >= 2 and s.isalnum() and valid_order(s):
return True
else:
return False
def valid_order(c):
n = []
l = list(c[2:len(c)])
for i in c:
if i.isdigit():
n += i
if n and n[0] == "0":
return False
if len(l) == 2:
if l[0].isdigit() and l[1].isalpha():
return False
if len(l) == 3:
if l[0].isdigit():
if l[1].isalpha() or l[2].isalpha():
return False
else:
if l[1].isdigit() and l[2].isalpha():
return False
if len(l) == 4:
if l[0].isdigit():
if l[1].isalpha() or l[2].isalpha() or l[3].isalpha():
return False
else:
if l[1].isdigit():
if l[2].isalpha() or l[3].isalpha():
return False
else:
if l[2].isdigit() and l[3].isalpha():
return False
else:
return True
main()

Using a recursive bisection search to check if a character is in a string

My code is here:
def isIn(char, aStr):
mid = len(aStr)//2
if len(aStr)==0:
return False
elif len(aStr)==1:
if char == aStr:
return True
elif aStr[mid] == char:
return True
if mid == 0 and len(aStr) != 1:
return False
else:
if char > aStr[mid]:
return isIn(char,aStr[mid:] )
else:
return isIn(char,aStr[0:mid])
my code works for when the character is present in the string, if the test case is such that if the character that I want to search in the string is not actually present in the string, then the code goes into an infinite loop.
For example in the test case isIn('m','iloruuyz') the code goes into an infinite loop.
On the if len(aStr) == 1: condition, you only return True if the condition is met, but not False if the condition is not, that is where the infinite loop is occuring :)
def isIn(char, aStr):
mid = len(aStr)//2
if len(aStr)==0:
return False
elif len(aStr)==1:
if char == aStr:
return True
else: # Else return false to stop the infinite loop
return False
elif aStr[mid] == char:
return True
if mid == 0 and len(aStr) != 1:
return False
else:
if char > aStr[mid]:
return isIn(char,aStr[mid:] )
else:
return isIn(char,aStr[0:mid])

Python: A function to check the last string

the function takes user's input (a string). It should return True if the last character appears more than once in the string, regardless if it's upper or lower case, otherwise it returns False.
What is wrong with the code?
def last_early(word):
word.lower()
if word.count(word[-1]) > 1:
print("True")
else:
print("False")
This is what I expect:
>>> last_early("happy birthday")
True
>>> last_early("best of luck")
False
>>> last_early("Wow")
True
>>> last_early("X")
False
Try:
def last_early(word):
lower_word = word.lower() # word.lower won't change word itself
if lower_word.count(lower_word[-1]) > 1:
return True
else:
return False
you can test by running:
def testLastEarly():
print("testing last_early()...",end="")
assert(last_early("happy birthday") == True)
assert(last_early("best of luck") == False)
assert(last_early("Wow") == True)
assert(last_early("X") == False)
print("pass")
testLastEarly()
if you want to try more exercise, check out here

I am trying to reduce my code to make it simpler by removing the indexes

This is my recursive function named find(text,substring) that will return the substring if the substring is inside the text or return an empty string if substring is not inside the text. Another function named is_string_there(text, string) to test the find function. The function will return True if the string is inside the text or False if the string is not inside the text.
Am I able to cancel out text index and substring index to remove the two (0,0) at the print coding area to reduce my code to make it simpler and easier to understand so i can teach my students
def find(text, substring, text_index, substring_index):
if text_index == len(text) and substring_index != len(substring):
return False
if substring_index == len(substring):
return True
if text[text_index] == substring[substring_index]:
return find(text, substring, text_index+1, substring_index+1)
return False
def oo(text, substring, text_index, substring_index):
if text_index == len(text):
return False
if text[text_index] == substring[substring_index]:
if find(text, substring, text_index, substring_index):
return True
else:
return oo(text, substring, text_index+1, substring_index)
return oo(text , substring, text_index+1, substring_index)
print(oo("I love pie", "pie",0,0))
print(oo("I love pie1", "pie1",0,0))
Well if you want to remove the indexes permanently from the print commands, you could just use a class. This way you can even create other functions to take user input etc and take advantage of class variables for readability. Not sure if if cases should in form if-elif-else though:
class test():
def __init__(self):
self.reset()
self.run()
def reset(self):
self.substring_index = 0 #instead of putting in function they are now class variables
self.text_index = 0
def run(self):#more stuff can be done here
print(self.oo("I love pie","pie"))
self.reset() #reset the class variables for each step
print(self.oo("I love pie1","pie1"))
def find(self,text, substring): #pretty much the same code just using class variables and class methods
if self.text_index == len(text) and self.substring_index != len(substring):
return False
elif self.substring_index == len(substring):
return True
elif text[self.text_index] == substring[self.substring_index]:
self.text_index +=1
self.substring_index +=1
return self.find(text, substring)
else:
return False
def oo(self,text, substring):
if self.text_index == len(text):
return False
elif text[self.text_index] == substring[self.substring_index]:
if self.find(text, substring):
return True
else:
self.text_index +=1
return oo(text, substring)
else:
self.text_index +=1
return self.oo(text , substring)
if __name__=='__main__':
test()
Although just for reference, a super simple way for the problem is actually:
def oo(text,substring):
if substring in text:
return True
else:
return False
AS mentioned in comments:
def oo(text,substring):
if text.find(substring) == 0:
return True
else:
return False
Returns 0 if exists in text, -1 if not.
Interesting expansion possible when considering uppercase or lowercase diffrences. 'A' != 'a'
In your code, you use oo() to check if a character matches, and then calls find() to check if the rest of the characters match. Instead of checking character-by-character, you could use the idea of checking string equality. In your oo() function, you can check if the substring is equal to a splice of the original text. This will reduce your code but will make your find() function obsolete, while still serving as a simple demonstration of recursion.
def oo(text, substring, index):
if index == len(text):
return False
start = index
end = start + len(substring)
if text[start:end] == substring:
return True
else:
return oo(text, substring, index+1)
print(oo("I love pie", "pie",0))
print(oo("I love pie1", "pie1",0))
print(oo("I love pie", "pie1",0))
print(oo("I love pie1", "pie",0))
print(oo("pie", "pie",0))
print(oo("pi", "pie1",0))
print(oo("pie1", "pie",1))
Output:
True
True
False
True
True
False
False

Categories