Palindrome Function Issue - python

I was writing a function to see whether a string is a palindrome or not and came across an issue with my code. It seems to provide the right answer to most strings, but not to all!
Here it is:
def isPalindrome(string):
for letter in string:
if letter == string[(len(string)-1-string.index(letter))]:
return True
else:
return False
What is wrong with it? Thanks!

Use string slicing
string[start:stop:step]
string[::-1]
Starts from the end and moves towards the beginning, one step at a time.
In other words, slice the word, beginning at last index and move towards the first index.
See String Slicing
This is the most pythonic way to solve the problem.
def palindrome(word: str) -> bool:
return word == word[::-1]
palindrom('scarf')
>>> False # because scarf != fracs
palindrome('rotator')
>>> True # because rotator == rotator
Regarding your current implementation
Your function stops after the first letter because the return statement immediately stops the function and returns the value.
There are many ways to fix your code
Change return to yield, which will return a generator.
Iterating the generator, with list(), will then show True or False for each letter
The result is a palindrome if all() the items are True
This is not an efficient way to solve this problem.
def isPalindrome(string):
for letter in string:
if letter == string[(len(string)-1-string.index(letter))]:
yield True
else:
yield False
test = list(isPalindrome('rotator'))
print(test)
>>> [True, True, True, True, True, True, True]
print(all(test) == True)
>>> True
test = list(isPalindrome('scarf'))
print(test)
>>> [False, False, True, False, False]
print(all(test) == True)
>>> False

Currently you're returning true in cases where not the whole word matches. Only return False if any of the letters dont match, and return True at the end of the loop.
def isPalindrome(string):
for letter in string:
if not letter == string[(len(string)-1-string.index(letter))]:
return False
return True

Related

Why is if statement returning False?

ALL_CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
HIDDEN = '^'`
def is_bonus_letter(lowercase_letter: str, phrase_puzzle: str,
current_view: str) -> bool:
"""Return True if and only if lowercase_letter is a bonus letter related
to phrase_puzzle and current_view.
>>> is_bonus_letter('k', 'talk', 't^l^')
True
>>> is_bonus_letter('l', 'love', 'l^v^')
False
"""
if ((lowercase_letter in ALL_CONSONANTS) and
(lowercase_letter in phrase_puzzle) and
(lowercase_letter in HIDDEN)):
return True
else:
return False
print(is_bonus_letter('k', 'talk', 't^l^')) # -> False
The output of is_bonus_letter('k', 'talk', 't^l^') should be True, but I keep getting False.
Why?
You're checking lowercase_letter in HIDDEN which is false since HIDDEN = '^' and lowercase_letter is t which does not exist in ^
Perhaps you meant to check lowercase_letter in current_view, as it would seem current_view is unused?
In general when you have two options, returning true or false, depending on many conditions, you can quickly find the answer by commenting out all of the conditions, then adding one back at a time until you pin point which one is causing it
Your program returns False because 'k' is not in 't^l^'. if you want it to return True, lowercase_letter would have to be 't' or 'l', OR you would have to edit your if statement. Right now, your program returns false because (lowercase_letter in HIDDEN) is false.

How to make letters in a string match

I wasn't sure what to title it, but I'm writing a function that checks if a phrase is a palindrome or not. If something is capitalized or not doesn't matter and if there are other characters it will remove them. If the string is the same forwards and backwards (that's what a palindrome is) then it will be a Boolean True, and a Boolean False if it isn't. For example:
is_palindrome('ta.cocat')
#It would return
True
is_palidrome('Tacocat')
#It would return
True
is_palindrome('tacodog')
#It would return
False
I've written code that will take out extra characters, but I can't figure out how to make it that capitalization doesn't matter.
#Strip non-alpha
def to_alphanum(str):
return ''.join([char for char in str if char.isalnum()])
#Palindromes
def is_palindrome(str):
str = to_alphanum(str)
if(str==str[::-1]):
return True
else:
return False
#Here's examples about what it returns
is_palindrome('taco.cat')
True
is_palindrome('Tacocat')
>>> False
just use the lower function on your input string, so that case doesnt matters in your function
str = to_alphanum(str).lower()
You can simply use:
def isPalindrome(s):
s = to_alphanum(s).lower()
rev = s[::-1]
# Checking if both string are equal or not
if (s == rev):
return True
return False
s1 = "malayalam"
>>> isPalindrome(s1)
True

For loop terminating early in nested ifs and function due to return

I am trying to solve the following practice question:
"Imagine you're writing the software for an inventory system for
a store. Part of the software needs to check to see if inputted
product codes are valid.
A product code is valid if all of the following conditions are
true:
The length of the product code is a multiple of 4. It could
be 4, 8, 12, 16, 20, etc. characters long.
Every character in the product code is either an uppercase
character or a numeral. No lowercase letters or punctuation
marks are permitted.
The character sequence "A1" appears somewhere in the
product code.
Write a function called valid_product_code. valid_product_code
should have one parameter, a string. It should return True if
the string is a valid product code, and False if it is not."
def valid_product_code(code):
if len(code)%4 == 0:
if "A1" in code:
if code.isalnum():
for character in code:
#print(character)
#print statement above when uncommented used to
#check if the loop is actually running as intended
if character.isupper() or character.isdigit():
return True
else:
return False
else:
return False
else:
return False
else:
return False
The practice question had several test strings, of which they included the following:
print(valid_product_code("A12B44BP"))
print(valid_product_code("BFDSAUSA98932RWEFOEWA9FEAA1DSFSF"))
print(valid_product_code("A1BBD5"))
print(valid_product_code("BDD5664S"))
print(valid_product_code("66aBSaA1fdsv"))
My code worked for the first four examples, resulting in True, True, False, False but while the last one should be False, I got True. After attempting some debugging (hence the print(character) in the for loop and changing the return True and return False to print(True) and print(False) statements respectively), the print statements I used to check indicated that lowercase letters all had False values whereas numbers and uppercase letters had True values as intended.
I had no problems with the 3 outer if statements, but once I needed to isolate lowercase characters I thought a for-each loop would suffice but the fact that this is a function means return is terminating my function prematurely and not allowing me to actually indicate that the presence of even a single lowercase letter in the whole string should render the value of the whole string as False. I feel something is missing, like maybe that I am putting my return statements in the wrong place, or have I simply approached this question the wrong way?
Please help and thanks in advance!
Your innermost loop is not implemented correctly. At the moment, if character.isupper() or character.isdigit(): will return True as soon as it detects the first 6.
You need to check for each element. This can be done in the following way. I am highlighting the modified lines by a comment #
def valid_product_code(code):
if len(code)%4 == 0:
if "A1" in code:
if code.isalnum():
for character in code:
if not (character.isupper() or character.isdigit()): # <---
return False # <----
return True # <---
else:
return False
else:
return False
else:
return False
print(valid_product_code("A12B44BP"))
print(valid_product_code("BFDSAUSA98932RWEFOEWA9FEAA1DSFSF"))
print(valid_product_code("A1BBD5"))
print(valid_product_code("BDD5664S"))
print(valid_product_code("66aBSaA1fdsv"))
True
True
False
False
False
Alternatively, you can combine your if statements to make the code more compact as
def valid_product_code(code):
if len(code)%4 == 0 and "A1" in code and code.isalnum():
for character in code:
if not (character.isupper() or character.isdigit()):
return False
return True
else:
return False

if...else.. compare character list and string by python

I am writing an for loop comparing the character in list and string, then return False if the character is not same. But I keep receiving True. Can someone explain what is wrong with my code?
def compare (sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)+1):
if orig[i] == sofar[i]:
return True
else:
return False
return False
here is the result i got:
In [29]: compare (['a','v','c','c','s'], 'abccs')
Out[29]: True
But it suppose to be False
You could just join the characters back into a string
def compare (sofar, orig):
return ''.join(sofar) == orig
Otherwise, if you wanted a loop, you need to compare all characters before you return True. You can return False when the first does not match
Here's another one liner using all() over a loop of zipped characters.
You will need the length check before this statement
return all(x == y for x, y in zip(sofar, orig))
Or going back to the original code, invert your logic
def compare (sofar, orig):
if len(sofar) != len(orig):
return False
for i in range(len(orig)):
if orig[i] != sofar[i]:
return False
return True
If your function reaches a return statement, that's it. Your function has returned a value and it will not continue running.
You can use a generator to implement your logic. The below solution allows you to iterate lazily; retrieve a Boolean list with a letterwise comparison via list; or check if all letters align via all.
def compare(sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)):
if orig[i] == sofar[i]:
yield True
else:
yield False
res = list(compare(['a','v','c','c','s'], 'abccs'))
# [True, False, True, True, True]
res = all(compare(['a','v','c','c','s'], 'abccs'))
# False
Another way of writing your logic without explicit iteration:
lst = ['a','v','c','c','s']
mystr = 'abccs'
res = ''.join(lst) == mystr
The statement return is exit from your function.
So your prog only compares the first element.
if orig[i] != sofar[i]:
return False
would do it

See if string contains substring

I was looking for a way to write code that checks whether a certain string is a part of another string. I understand that it is easy to do when we have numbers, but I don't know how to do it with strings.
For example, I have this function
a = is_part("motherland", "land")
I need to know that "land" is a part of the word "motherland" (return True or False). Is it possible to check this?
UPDATE: How can I create a restriction when the second word always has to be in the end of the first one. For example, in case when I check whether "eight" is a part of "eighteen" it returns False because "eight" is not at the end of the first word
This should help:
>>> "land" in "motherland"
True
>>> "banana" in "motherland"
False
Here is a function that determines whether a string target is contained within another string some_string.
def is_part(some_string, target):
return target in some_string
>>> is_part('motherland', 'land')
True
>>> is_part('motherland', 'father')
False
>>> is_part('motherland', '')
True
If you don't like an empty string returning true, change the return statement to
return (target in some_string) if target else False
If, on the other hand, you need to implement it yourself:
def is_part(some_string, target):
if target:
target_len = len(target)
for i in range(len(some_string)):
if some_string[i:i+target_len] == target:
return True
return False

Categories

Resources