I'm designing a guess word game and I need some help with one of the functions.
The function receives 2 inputs and returns true or false.
The input my_word contains letters that were guessed and match to a certain word.
The input other_word is some word to compare with my_input.
examples:
>>> match_with_gaps("te_ t", "tact")
False
>>> match_with_gaps("a_ _ le", "apple")
True
>>> match_with_gaps("_ pple", "apple")
True
>>> match_with_gaps("a_ ple", "apple")
False
My problem is applying it to return a False as in the last example and I'm not sure how to do it. This is what I have done so far. It works but not for a case when a one guessed letter in my_word appears 2 time in other_word. In this case I'm returning true but it should be False.
The inputs must be the exactly in the format as in the example (space after underscore).
def match_with_gaps(my_word, other_word):
myWord = []
otherWord = []
myWord_noUnderLine = []
for x in my_word:
if x != " ": # remove spaces
myWord.append(x)
for x in myWord:
if x != "_": # remove underscore
myWord_noUnderLine.append(x)
for y in other_word:
otherWord.append(y)
match = ( [i for i, j in zip(myWord, otherWord) if i == j] ) # zip together letter by letter to a set
if len(match) == len(myWord_noUnderLine): # compare length with word with no underscore
return True
else:
return False
my_word = "a_ ple"
other_word = "apple"
print(match_with_gaps(my_word, other_word))
You could create a "no space" version and a "no space, no underscore" version of your string and then compare each character to see if non underscore characters matched or if characters corresponding to an underscore have already been used. For example:
def match_with_gaps(match, guess):
nospace = match.replace(' ', '')
used = nospace.replace('_', '')
for a, b in zip(nospace, guess):
if (a != '_' and a != b) or (a == '_' and b in used):
return False
return True
print(match_with_gaps("te_ t", "tact"))
# False
print(match_with_gaps("a_ _ le", "apple"))
# True
print(match_with_gaps("_ pple", "apple"))
# True
print(match_with_gaps("a_ ple", "apple"))
# False
This line here:
if len(match) == len(myWord_noUnderLine)
Will not give you what you want right now. In the "a_ ple" example, both the space and the "_" are removed, so your myWord_noUnderLine variable will be "aple", so checking for a length match will surely fail between "aple" and "apple"
Related
“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
Can someone tell me why after returning a boolean of False my code goes backwards and chooses True also even though the False was the right output I see this happening in the debugger, I only found this happening with this specific example. So the function of my code is to take a pattern from user and see if it matches the word given by the user, the format of a pattern is "?ead" which would match with the word lead, the question mark is just a placeholder for any character so it can be anything but every other character has to be the same.
n = 0
def match(pattern, word):
global n
if n != len(word): # setting a base case for the recurrsion so it stops at the end of the word
if pattern == "" and word == "":
pass
elif pattern == '' or word == '':
pass
elif len(word) != len(pattern):
return False
if word[n:n+1] == pattern[n:n+1] or pattern[n:n+1] == '?': # goes through each character and compares them for each
n = n +1
match(pattern, word)
print("same")
return True # This is where the code goes back to and returns true after already returning false down below in the else statement.
else:
print("not same")
return False
match("?ut","cat")
The pattern my code fails for "?ut" and the word is "cat", the code sees that the first character is fine since "?" is just a placeholder and it also sees that the second term does not match so it should evaluate to false which it does but then immediately exits and evaluates to true and all this needs to be done with recursion and no loops.
You are trying to do recursion here. It can be done like this:
def match(pattern, word):
#Little debug for you to see what is happening
print (pattern, word)
if len(pattern) != len(word):
return False
if not word and not pattern:
# last round with empty strings, all same this far
return True
if pattern[0] != word[0] and pattern[0] != "?":
return False
# reduce both strings and go to next round
return match(pattern[1:], word[1:])
So you reduce both pattern and word and if you find that they don't match return false. If you get to the end, return True.
You do not return the result of match but return True. You should simplify your cases.
if word[n:n+1] == pattern[n:n+1] or pattern[n:n+1] == '?':
n = n +1
match(pattern, word) # this can return True OR False
print("same")
return True # You always return True
# return match(pattern, word) instead
There is no need for a global "counter" - if you recurse, shorten your pattern/word until nothing is left:
def match(pattern, word):
if len(pattern) != len(word):
return False
# done all I can do
if pattern == "" and word == "":
return True
# no comparison if pattern is ?
if pattern[0] == "?":
# recurse with 1 shorter pattern/word
return match(pattern[1:], word[1:])
# same letters
elif pattern[0] == word[0]:
# recurse with 1 shorter pattern/word
return match(pattern[1:], word[1:])
# different
return False
for pat,wrd in [("?ut","cat"), ("ok","ok"), ("?k","ok"),
("o?","ok"), ("",""), ("tooShort","veryLongWord")]:
print(pat,wrd, "=>", "same" if match(pat,wrd) else "different")
Output:
?ut cat => different
ok ok => same
?k ok => same
o? ok => same
=> same
tooShort veryLongWord => different
Or use the "short" version that does not recurse:
def match(pattern, word):
return len(pattern)==len(word) and all(
(p==w or p == "?" for p,w in zip(pattern, word)))
You should return the result you get back from recursion. Currently you ignore it.
There are some other issues:
Don't use global variables. If you make another call to match, then n will still be the value it had after the first call, and so you'll get an unreliable result from the second call. Instead make it an argument to your function. You can give it a default value.
The condition if pattern == "" and word == "": can never be true, since you already had assured that n != len(word), and as n starts with 0, that if condition would have been false if word was the empty string.
When you pass in the first if blocks, the other code below is still executed, and so you'd make an invalid index reference in the string.
Adding another condition where you delimit strings with single quotes instead of double quotes is not changing anything. You still compare the same strings.
It is overkill to compare slices of one character. Just retrieve the single character you want to compare. So word[n] instead of word[n:n+1]
Don't print the result inside the function. Print at the caller's side.
Correction:
def match(pattern, word, n=0):
if len(word) != len(pattern):
return False
if n >= len(word):
return True
if word[n] != pattern[n] and pattern[n] != '?':
return False
return match(pattern, word, n + 1)
print(match("?ut","cat"))
Not your question, but this kind of recursion is a case of tail recursion, and so it could be written with simple iteration:
def match(pattern, word):
if len(word) != len(pattern):
return False
for i, pat in enumerate(pattern):
if word[i] != pat and pat != '?':
return False
return True
When you are confortable with comprehension syntax you can write that also like this:
def match(pattern, word):
return len(word) == len(pattern) and all(
pat in ('?', ch) for ch, pat in zip(word, pattern)
)
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.
I did an implementation on checking if whether a string has balanced parentheses or not using a STACK only. But I checked for balanced parentheses when the string has words. For example:
>>> is_paren_balanced("[{whoa (this is rough [how do I do this!])}]")
True
I was successful in doing that. However, I am not trying to check for a case if the string has NO parenthesis. And then i got this result:
>>> is_paren_balanced("Hi i love food.")
no parenthesis
True
>>> is_paren_balanced("[{whoa (this is rough [how do I do this!])}]")
no parenthesis
False
For the first result, I don't want the boolean result as thats kind of vague. I'm trying to show the user that the string has no parenthesis so it is neither True or False. I just want the print statement shown saying "no parentheses here" or whatever. For the second result, obviously just the boolean result and it shouldve returned True.
Any suggestions? I'm stumped.
Here is the code I'm practicing with:
from stack import Stack
def is_match(p1, p2):
if p1 == "(" and p2 == ")":
return True
elif p1 == "{" and p2 == "}":
return True
elif p1 == "[" and p2 == "]":
return True
else:
return False
def is_paren_balanced(paren_str):
s = Stack() #initialize a stack object
is_balanced = True #boolean flag: whether the str has balanced parenthesis or not
# then set to false if otherwise
index = 0 # keep track of where we are in the string
paren_str = paren_str.replace(" ", "") #accounts for possible spaces in the input
while index < len(paren_str) and is_balanced:
paren = paren_str[index]
if paren in "({[":
s.push(paren)
elif paren in ")}]":
if s.is_empty():
is_balanced = False
else:
top = s.pop()
if not is_match(top, paren):
is_balanced = False
else:
if paren not in "({[]})":
print("no parenthesis")
break
index += 1
if s.is_empty() and is_balanced:
return True
else:
return False
Sorry if it doesn't seem pythonic. I was just mostly exploring with this problem and will edit and improve later on.
You can use either regex or list comprehension to get the total amount of parenthesis first:
import re
def all_parenthesis(msg):
left = re.findall(r"[\[{(]",msg)
right = re.findall(r"[\]|})]",msg)
if not left and not right:
return "No parenthesis"
#or
def check_balance(msg):
d = {"[":"]",
"{":"}",
"(":")"}
left = [char for char in msg if char in d]
right = [char for char in reversed(msg) if char in d.values()]
#if not left not right...
But if you already constructed a list of parenthesis on both sides, why don't go ahead and compare them instead? Could be something like this:
def check_balance(msg):
d = {"[":"]",
"{":"}",
"(":")"}
left = [char for char in msg if char in d]
right = [char for char in reversed(msg) if char in d.values()]
if not left and not right:
return "No parenthesis"
elif len(left) != len(right):
return False
for a, b in zip(left,right):
if d.get(a) != b:
return False
return True
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