Why does the execution change after adding second half of the code? - python

I am facing difficulty while writing a code for testing for a pangram (a string that contains all 26 alphabets at least once).
When executed based on first part as follows:
def ispangram(x):
alphabet="abcdefghijklmnopqrstuvwxyz"
for i in alphabet:
if i in x.lower():
return True
The code works fine.
But if I add the else condition:
def ispangram(x):
alphabet="abcdefghijklmnopqrstuvwxyz"
for i in alphabet:
if i in x.lower():
return True
else i not in x.lower():
return False
The code returns every input as a valid pangram.
Could someone please help me understand what is going wrong here?

You aren't checking every letter in the alphabet. You are only checking if the word contains the letter a. Let's examine the control flow
def is_pangram(x):
x = x.lower()
alphabet="abcdefghijklmnopqrstuvwxyz"
# we begin iteration here
for i in alphabet:
# we check if the letter is in the word
if i in x:
# we return! This will stop execution at the first True
# which isn't always the case
return True
else:
# we return again! since we've covered all cases, you will
# only be checking for a
return False
To fix this, you can do one of two things. Using a loop, you can just check if letters are not in x, returning False if they are not, and returning True at the end:
def is_pangram(x):
x = x.lower()
alphabet="abcdefghijklmnopqrstuvwxyz"
for i in alphabet:
if i not in x:
return False
# this means we made it through the loop with no breaks
return True
Alternatively, you can use the all operator to check if all of the letters in the alphabet are in the word, which returns True, otherwise it returns False
def is_pangram(x):
x = x.lower()
alphabet="abcdefghijklmnopqrstuvwxyz"
return all(i in x for i in alphabet)

Your first function will return true for any string that contains any letter. You need to verify that each letter is in your input string:
import string
def ispangram(x):
x = x.lower()
for c in string.ascii_lowercase:
if c not in x:
# a letter is not in the input string, so the input string is not a pangram
return False
# if we got here, each letter is in the input string
return True

Related

Trying to make a python recursive function that checks if a character is in the given string however i have failed to

def q5(s,c):
if s == "":
return s
elif c != s[0]:
return False
else:
return True
return q5(s[1:], c)
Takes an string s and a single-character string c as inputs and uses recursion to determine if s contains the character c, returning True if it does and False if it does not.
and I'm using recursion to process s one character at a time and determine if c is contained in s.
Args:
s (str): input string
, c (str): single character
Im having issues doing this and when I do q5("HI", "H") it returns true because "H" is in "HI" however when I do q5("HI", "I") it returns false even though "I" is also in the string "HI".
The issue is you're returning False if the first character doesn't match. You need to return True if it does match and then recurse if it doesn't; eventually you return False if you get to the end of the string.
def q5(s,c):
if s == "":
return False
elif c == s[0]:
return True
else:
return q5(s[1:], c)
You basically want to know if the first character of the string equals the search character or that character occurs in the rest of the string.
You can translate that idea directly and very succinctly with:
def q5(s,c):
if s == "":
return False
return s[0] == c or q5(s[1:], c)
q5("HI", "I")
# True
q5("HI", "H")
# True
q5("HI", "f")
# False
There is a simpler way to achieve this without needing recursion, you can check for the letter like so:
def q5(s,c):
if c in s:
return True
else:
return False

How to make Python differentiate between upper and lower characters.

Hello guys I hope you will help me with a small problem that I did not figured out yet.
Here is the description of the homework to have an idea first about what I am working on.
" In this part of the homework, you will write a program that inputs two different
characters in the form of "c1-c2", where c1
is the first character and c2
is the second
character. You need to check the validity of this input. That is, the input should
start with a letter, followed by a dash (-), and it should end with another letter case
insensitively (it means that "a" and "A" are the same characters). Please note that
the characters to be obtained from the user must be different from each other. In
case that the user enters an invalid input, your program should continuously
prompt for the required value until (s)he enters a valid one."
Here is some sample runs:
Please enter two different characters in the form c1-c2: a-A
Invalid input!
Please enter two different characters in the form c1-c2: a-B
(The program should stop if it is correct.)
Here is what I tried so far:
ascii_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
def process(Z):
if Z[0] in ascii_letters:
return True
if Z[1] == '-':
return True
if Z[2] in ascii_letters:
return True
if Z[0] != Z[2]:
return True
if Z[0] != Z[2].upper():
return True
if Z[0] != Z[2].lower():
return True
X = False
while X == False:
ask = input("Please enter two different characters in the form c1-c2: ")
if process(ask) == False :
print("Invalid input!")
else:
break
Here your process almost always terminate at the first check:
def process(Z):
if Z[0] in ascii_letters:
return True
You need to nest your condition, and 'return' only when all the conditions are filled, a fast example:
def process(Z):
if Z[0] in ascii_letters:
if Z[1] == '-':
if Z[2] in ascii_letters:
return True
return False
Note you will want to check for that Z is the right size before accessing Z[2]. And you need as well to add the check about same-letter. So a solution for your problem would be:
def process(Z):
if len(Z) == 3
and Z[0] in ascii_letters
and Z[1] == '-'
and Z[2] in ascii_letters
and Z[0].upper() != Z[2].upper():
return True
return False
Strings have methods you can use to validate the input. Use them! You can split on '-' and verify you have 2 characters of length 1, check whether they are alphabetic and compare the upper case version of each.
def process(Z):
parts = Z.split("-")
return (len(parts)==2 and len(parts[0])==1 and len(parts[1])==1
and parts[0].isalpha()
and parts[0].upper() == parts[1].upper())
isalpha works for all unicode characters so you don't have to worry whether the user entered text in some strange language.
The inbuilt function -isalpha() will be helpful for your homework.
while True:
ask=input('Please enter two different characters in the form c1-c2: ')
if len(ask)!=3:
continue
if ask[1] == '-' and ask[0].isalpha() and ask[2].isalpha() and ask[0]!=ask[2]:
break
The isalpha() function returns True if the given string has all alphabets.
The correct way to handle this is with regular expressions. Their is a regex library as part of the standard python library.
import re
u_input = 'your string'
def validate(input):
# chars must be different
if input[0] == input[-1:]:
return False
# begin and end with upper or lower a-z with dash in middle
pattern = '[a-zA-Z]{1}-[a-zA-Z]{1}'
result = re.match(pattern, input)
# re.match returns None if no match
if not result:
return False:
else:
return True
I tried to make it as similar to your code as possible and it's quite simple to understand. I think I considered all required conditions. If not, tell me.
from string import ascii_letters
def validity_check(input_chars):
try:
# if cant be splitted raises Exception which results in restart
char_1, char_2 = input_chars.split("-")
# if characters not in alphabet restarts
chars_in_alphabet = char_1 in ascii_letters and char_2 in ascii_letters
if not chars_in_alphabet:
return False
# if characters are the same letter restarts
same_latter = char_1.lower() == char_2.lower()
if same_latter:
return False
# I'm not sure if you want to check if the first letter
# is small and the second one is capital
# if so add this block
# chars_letter_size = char_1 in ascii_letters.lower() and char_2 in ascii_letters.upper()
# if not chars_letter_size:
# return False
return True
except:
return False
while True:
ask = input("Please enter two different characters in the form c1-c2: ")
if validity_check(ask):
break

Checking a password

I think I have the right idea of solving this function, but I'm not sure why
I don't get the desired results shown in the docstring. Can anyone please help me fix this?
def check_password(s):
'''(str, bool)
>>> check_password('TopSecret')
False
>>> check_password('TopSecret15')
True
'''
for char in s:
if char.isdigit():
if char.islower():
if char.isupper():
return True
else:
return False
Your logic is flawed it should look like this:
def check_password(s):
has_digit = False
has_lower = False
has_upper = False
for char in s:
if char.isdigit():
has_digit = True
if char.islower():
has_lower = True
if char.isupper():
has_upper = True
# if all three are true return true
if has_digit and has_upper and has_lower:
return True
else:
return False
Now, let's talk about what's wrong with your code.
def check_password(s):
for char in s:
if char.isdigit():
if char.islower(): # we only get to this check if char was a digit
if char.isupper(): # we only get here if char was a digit and lower
# it is not possible to get here
# char would have to be a digit, lower, and upper
return True
else:
return False
As an example let's look at TopSecret15, we start with T
isdigit = False so we immediately return false for 'T'
We will continue to immediately return false until we get to '1'
Let's say we were on 1, isdigit would be true, but islower would be false so again it returns false
Do you see how it is impossible for all three of these to be true for the same char?
Your code is equivalent to:
if char.isdigit and char.islower and char.isupper:
# this will never happen
The reason this doesn't work is that for any given character, it first checks if it's a digit, then if it's lower, then if it's upper. Obviously, one character cannot be all three of these at once. You instead want to check each character to see if it's a digit, lowercase, or uppercase, and then flip a boolean value like has_upper. Then, after the for loop, you'll check to see if all of the boolean values are true.
See this answer:
https://stackoverflow.com/a/2990682/7579116
the best way to check if a password match all the requirements is by using a regex.
I've gone way overboard here (because I'm bored I guess) and whipped up an extensible password-checking system. Perhaps it will help clarify why your version doesn't do what you want (or maybe it won't).
The essential problem with your code is that it checks for a single characteristic instead each of the required characteristics.
def check_password(password):
# These are the characteristics we want a password to have:
characteristics = [
length(8), # At least 8 characters
lower_case(1), # At least 1 lower case letter
upper_case(1), # At least 1 upper case letter
number(1), # At least 1 number
]
# Check to see if the supplied password has *all* of the desired
# characteristics:
return all(
characteristic(password)
for characteristic in characteristics
)
def length(n=10):
# Ensure password has at least N characters
def check(password):
return len(password) >= n
return check
def lower_case(n=1):
# Ensure password has at least N lower case characters
def check(password):
count = 0
for char in password:
if char.islower():
count += 1
if count == n:
return True
return False
return check
def upper_case(n=1):
# Ensure password has at least N upper case characters
def check(password):
count = 0
for char in password:
if char.isupper():
count += 1
if count == n:
return True
return False
return check
def number(n=1):
# Ensure password has at least N numbers
def check(password):
count = 0
for char in password:
if char.isdigit():
count += 1
if count == n:
return True
return False
return check
# Doesn't have any numbers:
>>> print(check_password('TopSecret'))
False
# Acceptable:
>>> print(check_password('TopSecret15'))
True
# Has lower case, upper case, and number, but it's not long enough:
>>> print(check_password('Ab1'))
False
Notes:
Some parts of this are simplified in order to make it more clear what's going on (all of the check functions could be one-liners).
In a production system, password requirements will almost certainly change over time and you want to make sure that implementing additional requirements is easy.
A regular expression might not be as easy to understand or extend (although it might be a little faster, but that probably doesn't matter at all).
The approach above is somewhat similar to Django's password validation system.

Multiple characters in a string return a false boolean when trying to find a character in the string

#Function takes a character and a string and returns a boolean reflecting if
#the character is found in the string.
def isItThereS(letter, word):
letInWord = 0
for l in word:
if l == letter:
letInWord += 1
return letInWord == True
When I put it in the operator like
isItThereS("h","hello world")
True
but when I go to find a character that repeats like "l" or "o" it returns false.
isItThereS("l","hello world")
False
How would I go about getting that to not return false, but instead return True since the character is technically in the string?
you can simply use the in operator
def isItThereS(letter, word):
return letter in word
If you really want to use a custom function for that, change your return to return letInWord >= 1. As everything but 1 == True will evaluate to False. (So a more appropriate name for the function as is would be is_it_there_only_once).
Otherwise please use the solution provided by armak.

How do I check if a string contains ALL letters of the alphabet in python?

I am trying to write a python program that checks if a given string is a pangram - contains all letters of the alphabet.
Therefore, "We promptly judged antique ivory buckles for the next prize" should return True while any string that does not contain every letter of the alphabet at least once should return False.
I believe I should be using RegEx for this one, but I'm not sure how. It should look similar to this:
import sys
import re
input_string_array = sys.stdin.readlines()
input_string = input_string_array[0]
if (re.search('string contains every letter of the alphabet',input_string):
return True
else:
return False
This is not something I'd solve with a regular expression, no. Create a set of the lowercased string and check if it is a superset of the letters of the alphabet:
import string
alphabet = set(string.ascii_lowercase)
def ispangram(input_string):
return set(input_string.lower()) >= alphabet
Only if every letter of the alphabet is in the set created from the input text will it be a superset; by using a superset and not equality, you allow for punctuation, digits and whitespace, in addition to the (ASCII) letters.
Demo:
>>> import string
>>> alphabet = set(string.ascii_lowercase)
>>> input_string = 'We promptly judged antique ivory buckles for the next prize'
>>> set(input_string.lower()) >= alphabet
True
>>> set(input_string[:15].lower()) >= alphabet
False
This is my solution in python:
alphabet = "abcdefghijklmnopqrstuvwxyz"
sentence = input()
sentence = sentence.lower()
missing = ''
for letter in alphabet:
if letter not in sentence:
missing = missing+letter
if (len(missing) != 0):
print("missing", missing)
else:
print("pangram")
You dont need regex. What you want can be done in two lines with good space efficiency.
ms = itertools.chain(range(ord("a"),ord("z")),range(ord("A"),ord("Z")))
flag = all(chr(o) in string for o in ms)
That's it. string is the string you want to check. flag will be either True or False depending on if all chars are in string or not.
A pangram is a function that contains at least each letter of the alphabet.
I have tried in this way:
def pangram():
n = str(input('give me a word to check if it is a pangram:\n'))
n = n.lower()
n = n.replace(' ','')
if not isinstance(n, str):
return n, False
elif set(n) >= set('abcdefghijklmnopqrstuvxywz'):
return n, True
else:
return n, False
The function isinstance(n, str) checks if n is a string. The function set() gives us a set. For example set('penny') returns {'y', 'e', 'p', 'n'}... as you see it is a set without the repeated letters.
I was doing the same exercise today, maybe it's not the best aproach, but I think it's easy to understand.
def ispangram(s):
stringy = ''
flag = True
validLetters = "abcdefghijklmnopqrstuvwxyz"
#transform the given string in simple string with no symbols only letters
for char in s.lower():
if(char in validLetters):
stringy += char
#check if all the letters of the alphabet exist on the string
for char in validLetters:
if(char in stringy):
pass
else:
flag = False
break
return flag
if(ispangram("We promptly judged antique ivory buckles for the next prize")):
print("It's PANGRAM!")
else:
print("It's not Pangram :(")
import string
def ispangram(str1, alphabet=string.ascii_lowercase):
return ''.join(sorted(set(str1.lower().replace(" ","")))) == alphabet
First changed all alphabets to lowercase and then removed all spaces using replace. Then Converted into set to have unique chars and then used sorted function to sort alphabetically. As sorted function gives a list, so join func to join it without spaces and then compared it to all lowercase chars.
Here is my solution:
def isaPangrams(s):
alph = list(string.ascii_lowercase)
s = s.lower()
s = list(s)
for letter in alph:
if letter not in s:
print('not pangram')
present='false'
break
if letter in s:
present = 'true'
if present == 'true':
print('pangram')
if __name__ == '__main__':
s = input()
answer = isaPangrams(s)

Categories

Resources