.lower() Returning True when presented with 0 - python

I am attempting to complete a task of ensuring all characters in a string meet the following conditions:
Divisible by 4
Contains "A1" in the string
String only contains Uppercase and Numbers
For most strings the function works; however, I am returning a false False when a 0 is presented.
The problem is localized to the for loop (for character in string:) as shown by the output.
def valid_product_code(string):
if len(string) % 4 == 0:
print("String is divisible by 4")
if "A1" in string:
print("A1 is contained within string")
for character in string:
print(character)
if character == character.lower():
print("Character is a Lowercase")
return False
elif character == ("!"or "." or "," or ":"):
print("Character is punct")
return False
else:
return True
else:
return False
else:
return False
print(valid_product_code("0O3LG6EWN7AA1NI596LCVBRZ"))
The output of the code is as follows:
String is divisible by 4
A1 is contained within string
0
Character is a Lowercase
False

What you are doing is un-pythonic. Instead of using if character == character.lower():, use .islower().
.islower() returns True when there are no uppercase letters in the string and there is at least one lowercase letter. That's not the same thing as all characters being letters.

you need to use if character.islower(): not if character == character.lower(): because '0'.lower()=='0' so that if statement (if character == character.lower():) will always return true if your string contain any digit

The short answer is '0'.lower() == '0'. Instead of checking for bad characters (such as lower-case letters or punctuation), you should describe in Python what it means to be a good character.
In this case, being a good character simply means
'A' <= character <= 'Z' or '0' <= character <= '9'

Related

after u see a valid number, no letter can come after it. how can i solve this?

“All vanity plates must start with at least two letters.”
“… vanity plates may contain a maximum of 6 characters (letters or numbers) and a minimum of 2 characters.”
“Numbers cannot be used in the middle of a plate; they must come at the end. For example, AAA222 would be an acceptable … vanity plate; AAA22A would not be acceptable. The first number used cannot be a ‘0’.”
“No periods, spaces, or punctuation marks are allowed.”
I solved ever problem but i am having a difficult time solving the highlighted problem. AAA22A or AAA2A as invalid.
def is_valid(s):
# checks for at least 2 chars and a max of 6 characters
# and checks for at least 2 uppercase letters
if len(s) < 2 or len(s) > 6 and s[0:2].isalpha():
return False
# checks for periods, spaces, or punctuation marks
for i in s:
if i in [".", " ", "!", "?"]:
return False
# checks if numbers in string starts with 0
i = 0
while i < len(s):
if s[i].isalpha() == False:
if s[i] == "0":
return False
else:
break
i += 1
# after u see a valid number, no letter can come after it
# this is where the challenge is ,
for i in s[::-1]:
if s[i].isalpha() == True:
for j in s[::-2]:
if s[j].isalpha == False:
return False
else:
break
else:
break
# returns true if all the requirements are passed
return True
"""i tried to iterate in reverse order but that deems unsuccessful. Not sure how to solve. need help please."""
You can have a function to know if a letter comes after a number or use this piece of code directly:
def letter_after_number(s):
for i in range(len(s) - 1):
if s[i].isdigit() and s[i + 1].isalpha():
return False
return True
here the entire code:
def is_valid(s):
# checks for at least 2 chars and a max of 6 characters
# and checks for at least 2 uppercase letters
if len(s) < 2 or len(s) > 6 and s[0:2].isalpha():
return False
# checks for periods, spaces, or punctuation marks
for i in s:
if i in [".", " ", "!", "?"]:
return False
# checks if numbers in string starts with 0
i = 0
while i < len(s):
if s[i].isalpha() == False:
if s[i] == "0":
return False
else:
break
i += 1
# after u see a valid number, no letter can come after it
# this is where the challenge is ,
for i in range(len(s) - 1):
if s[i].isdigit() and s[i + 1].isalpha():
return False
# returns true if all the requirements are passed
return True
So, you don't have to go in reverse order to check if there's a letter. I would iterate over the letters until you get to a character that's a number. Once you do that, you can check that the rest of the characters are numbers.
If you did want to go in reverse, you can apply the same logic: iterate backwards, checking that you're only reading numbers. Once you hit a letter, check that the rest of the string is only letters. You can do this in multiple ways, such as using set operations or just checking the character is the correct type.
Also, note that you don't have to/shouldn't use True/False in the conditional statements. It's better to use something like if s[i].isalpha() and if not s[i].isalpha()
This could be a good use of regular expressions. This pattern only matches strings that have an optional group of letters followed by an optional group of numbers. The pattern also omits special characters by design.
import re
def is_valid(s):
if len(s) < 2 or len(s) > 6:
return False
# regular expression with two capture groups
pattern = "^([a-zA-Z]{0,6})([0-9]{0,6})$"
m = re.match(pattern, s)
if m is None:
return False
alpha = m.group(1)
numeric = m.group(2)
# first digit is not zero
if numeric[0]=="0":
return False
return True

How to check if a string is strictly contains both letters and numbers

How to check if a string is strictly contains both letters and numbers?
Following does not suffice?
def containsLettersAndNumber(input):
if input.isalnum():
return True
else:
return False
isAlnum = containsLettersAndNumber('abc') # Should return false
isAlnum = containsLettersAndNumber('123') # Should return false
isAlnum = containsLettersAndNumber('abc123') # Should return true
isAlnum = containsLettersAndNumber('abc123$#') # Should return true
Please note that It MUST contain both letters and numerals
Simplest approach using only string methods:
def containsLetterAndNumber(input):
return input.isalnum() and not input.isalpha() and not input.isdigit()
input.isalnum returns true iff all characters in S are alphanumeric,
input.isalpha returns false if input contains any non-alpha characters, and
input.isdigit return false if input contains any non-digit characters
Therefore, if input contains any non-alphanumeric characters, the first check is false. If not input.isalpha() then we know that input contains at least one non-alpha character - which must be a digit because we've checked input.isalnum(). Similarly, if not input.isdigit() is True then we know that input contains at least one non-digit character, which must be an alphabetic character.
You can loop through and keep track of if you've found a letter and if you've found a number:
def containsLetterAndNumber(input):
has_letter = False
has_number = False
for x in input:
if x.isalpha():
has_letter = True
elif x.isnumeric():
has_number = True
if has_letter and has_number:
return True
return False
Alternatively, a more pythonic but slower way:
def containsLetterAndNumber(input):
return any(x.isalpha() for x in input) and any(x.isnumeric() for x in input)
You can also use regexes bool(re.match('^[a-zA-Z0-9]+$', 'string'))

Check if input is all caps and numbers

I need to check if my input is all caps and numbers, it must also contain "A1" and be a multiple of 4.
def valid_product_code(string):
#A1 must be in string
if "A1" in string:
val = True
#String must be a multiple of 4
if len(string) % 4 == 0:
val = True
#Must only have capitals or numbers
if (char.isdigit() or char.islower() for char in string):
val=True
else:
val = False
return val
What am I doing wrong? When I test it, it only returns True
You need to add all keyword so it will check all of the characters, change the islower to isupper and you override the return value
def valid_product_code(string):
#A1 must be in string
if "A1" not in string:
return False
#String must be a multiple of 4
if len(string) % 4 != 0:
return False
#Must only have capitals or numbers
if not all(char.isdigit() or char.isupper() for char in string):
return False
return True
Try this out, it uses some regex to check and make sure all letters are capitalized
import re
def valid_product_code(string):
# Regex pattern to check for all caps
pattern = '^[A-Z0-9]*$'
# Validation
valid = False
# Check for all caps
if re.search(pattern, string):
# Check for A1
if "A1" in string:
# Check for multiple of 4
if len(string) % 4 == 0:
valid = True
return valid
Regex is a great use case for something like this. You could also modify your function to automatically convert the string to upper case with string.upper(). Then you can return the capitalize string along with validation check with return string, valid. This would eliminate the need to check for capital letters all together.

Why is my program not detecting uppercase characters?

I am asking the user to input a password. The program then determines if the password is valid if it meets certain criteria.
Here is the section in question.
for i in range(0, len(password)):
if(password[i].isdigit()==True):
isNum+=1
elif (password[i].isalpha()==True):
isLetter+=1
elif (password[i].isupper()==True):
isUpper+=1
My program detects numbers and letters just fine, but it doesn't detect uppercase letters. If I put in the password 1234Foxes, it will say that there are 4 letters, 4 numbers, and 8 total characters, but it states that there are 0 uppercase letters.
If isupper is true, isalpha must have been true since an uppercase letter is necessarily alphabetic. Since you're using elif, the conditions are exclusive, and the checks stop once the isalpha check is true.
Just don't use elif there if you want both checks to run:
for character in password:
if(character.isdigit()):
isNum += 1
elif (character.isalpha()):
isLetter += 1
if (character.isupper()):
isUpper += 1
I also got rid of the need to index password by iterating the String directly, and the redundant == True
your logic is correct, but, you need to check if a char is upper before if it is alpha. It's because every upper char is alpha, so, the last elif will never be reached. So, change your code position to this:
for i in range(0, len(password)):
if(password[i].isdigit()==True):
isNum+=1
# isupper() first from isalpha()
elif (password[i].isupper()==True):
isUpper+=1
elif (password[i].isalpha()==True):
isLetter+=1
And, another tip: you can go through every char of string without using indexing, like this:
for char in password:
if (char.isdigit()):
isNum += 1
elif (char.isupper()):
isUpper += 1
elif (char.isalpha()):
isLetter += 1
Since isdigit(), isalpha() and isupper() returns True or False, you don't need to check if it is True or False (no need the == operator), just put it into if statement.

Check python function determine isogram from codewars

An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case.
is_isogram("Dermatoglyphics" ) == true
is_isogram("aba" ) == false
is_isogram("moOse" ) == false # -- ignore letter case
Here is my code:
def is_isogram(string):
string = string.lower()
for char in string:
if string.count(char) > 1:
return False
else:
return True
And when I tried to run the test code Test.assert_equals(is_isogram("moOse"), False, "same chars may not be same case" ) It failed, but I thought I did convert everything into lowercase. Can someone help?
Try this:
def is_isogram(string):
string = string.lower()
for char in string:
if string.count(char) > 1:
return False
return True
In your code when is_isogram("moose") is called, it will see that the first character's ('m') count is not greater than 1. So it will return True. Once it hits the return statement, it will stop the execution for the rest string. So you should really write return True only after for-loop to make sure that the function checks for the whole string.
If however, at any point, it finds a character's count to be greater than 1, then it will simply return False and stop executing because there's no point of checking any more when one point is found where condition does not hold.
How about using sets? Casting the string into a set will drop the duplicate characters, causing isograms to return as True, as the length of the set won't differ from the length of the original string:
def is_isogram(s):
s = s.lower()
return len(set(s)) == len(s)
print is_isogram("Dermatoglyphics")
print is_isogram("aba")
print is_isogram("moOse")
print is_isogram("")
This outputs:
True
False
False
True
Try this :
def is_isogram(s):
string = s.lower()
if len(s) == len(set(string)):
return True
return False
Try this out:
def is_isogram(string):
return len(string) == len(set(string.lower()))
"Implement a function that determines whether a string that contains only letters is an isogram."
By using sets, you can create unique elements. So if there are any repeating numbers, it will only select one. By calling len() on these strings, you can compare the length to the original.
Sorry if I explained it poorly. I am working on this.
let us define an isogram well:
according to wikipedia An Isogram is a word in which no letter occurs more than once.
check here for more about an isogram
just remind letter
I write this code and it works for me :
def is_isogram(argument):
print(len(argument))
if isinstance(argument,str):
valeur=argument.lower()
if not argument:
return False
else:
for char in valeur:
if valeur.count(char)>1 or not char.isalpha():
return False
return True
else:
raise TypeError("need a string ")
NB: the hidden test is the fact that you must check if the char in the string is a alpha character a-z, when i add this it pass all the hiddens tests
up vote if this help
I reckon this might not be the best solution in terms of maximizing memory space and time. This answer is just for intuition purposes using a dictionary and two for loops:
def is_isogram(string):
#your code here
#create an empty dictionary
m={}
#loop through the string and check for repeating characters
for char in string:
#make all characters lower case to ignore case variations
char = char.lower()
if char in m:
m[char] += 1
else:
m[char] = 1
#loop through dictionary and get value counts.
for j, v in m.items():
#if there is a letter/character with a count > 1 return False
if v > 1:
return False
#Notice the scope of the "return True" command. It is outside.
return True

Categories