Time for another Python challenge. This time it’s the palindrome challenge. What is a palindrome? A palindrome is a word, number, phrase, or other sequence of characters which reads the same backward as forward. Some examples are level, radar, stats.
The goal is to take a string the user inputs, reverse the string and see if it’s identical backward as forward. I will divide my code into two functions:
- get_string
- check_palindrome
The first function simply takes the string that is input. The second function checks if it’s a palindrome and prints the result.
As always, let’s first start with a docstring:
"""Program to check if string is a palindrome"""
Then we create a function to get the string from the user. This code should look familiar if you went through the divisors challenge.
def get_string():
"""Get a string from user to be used in function to check for palindrome"""
# Get string from user with input() and return result
user_string = input("Please enter a string to check if it's a palindrome: ")
return user_string
Now for the more interesting part, to check if a string is a palindrome. To do that, we need to reverse the string. How can we do that? The easiest way is probably to use slicing. Let’s give an example using the REPL:
First we create a string, the word radar:
daniel@devasc:~/DevAsc$ python3 Python 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> word = "radar" >>>
If we want to access a specific letter of this word, we can use access it by index. For example, to access the first letter:
>>> word[0] 'r'
Notice that counting starts from from zero. If we want to access the last letter, it is accessible at -1:
>>> word[-1] 'r'
We can also access a range of letters, a slice, by specifying a start and stop with a colon in between. For example, the three first ones, with a range from 0 to 3, because the stop index is not inclusive:
>>> word[0:3] 'rad'
It’s also possible to use a stepping. What if we want to access the entire string but only every other letter? We can do that by specifying 0:6:2. Start at index 0, stop at 6 not inclusive, with a stepping of 2.
>>> word[0:6:2] 'rdr'
The drawback here though is that this is not a generic approach since we have specified the stop manually. There are defaults when using slicing that we can leverage to write this more efficiently. The defaults, when using a positive stepping, are these:
- Start at index 0
- End where the string ends
- Stepping of 1
This means that we can access the slice with ::2, where we are using the default values for start and stop, as indicated by the colon, meaning to start at 0 and end where the string ends.
>>> word[::2] 'rdr'
Awesome! So how do we then find the reverse of a string? The trick is to use a negative stepping. This is where things can get a bit confusing. When using a negative stepping, the defaults for start and stop change. The defaults are then these:
- Start at the end of the string
- Stop at the beginning of the string
This means that we can reverse a string by using ::-1 where the first colon means to start at the end of string, go to the start of the string, with a stepping of -1, that is, go one step backward each time.
>>> word[::-1] 'radar'
Great. Now let’s write this as a function:
def check_palindrome(user_string):
"""Reverse string from user and check if palindrome"""
user_string_reverse = user_string[::-1]
if user_string_reverse == user_string:
print("It's a palindrome!")
else:
print("It's NOT a palindrome!")
We store the user_string in reverse in user_string_reverse. Then we check if they are equal. If they are, it’s a palindrome!
We must, of course, run the functions:
if __name__ == "__main__":
user_string = get_string()
check_palindrome(user_string)
When we run the code, this is what it looks like:
l@devasc:~/DevAsc$ python3 palindrome.py Please enter a string to check if it's a palindrome: radar It's a palindrome! daniel@devasc:~/DevAsc$ python3 palindrome.py Please enter a string to check if it's a palindrome: boat It's NOT a palindrome! daniel@devasc:~/DevAsc$
Finally, here’s the entire code:
"""Program to check if string is a palindrome"""
def get_string():
"""Get a string from user to be used in function to check for palindrome"""
# Get string from user with input() and return result
user_string = input("Please enter a string to check if it's a palindrome: ")
return user_string
def check_palindrome(user_string):
"""Reverse string from user and check if palindrome"""
user_string_reverse = user_string[::-1]
if user_string_reverse == user_string:
print("It's a palindrome!")
else:
print("It's NOT a palindrome!")
if __name__ == "__main__":
user_string = get_string()
check_palindrome(user_string)
It is available via Github as well.
Bonus: There’s another way of solving this challenge, with a For loop, although slicing is the preferred method. It looks like this:
daniel@devasc:~/DevAsc/Python-challenges$ python3 Python 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> word = "radar" >>> reverse = "" >>> for i in range(len(word)): ... reverse += word[len(word)-1-i] ... >>> print(reverse) radar >>>
We have the string radar stored in word. We also have an empty string called reverse. We can iterate through word. To do this, we use a for loop that loops through range(len(word)), that is, the length of the word.
We then add letters to reverse, starting at the end. Why do we have len(word)-1? Because of the zero index. Otherwise we would try to access an index that is not available. Why -i at the end? So that we move towards the start of the string. Note that the iterator is 0 when it starts, then it’s 1, 2, 3, and so on.
Happy coding!