1. Introduction
A palindrome is a sequence of characters that reads the same forwards and backward, such as madam, racecar, etc.
In this tutorial, we’ll look at how to check if a string is palindrome in Scala.
2. Assumptions
In this tutorial, we consider only alphanumeric characters when checking for palindromes, disregarding any special characters. Additionally, we use case-insensitive comparison for all the characters involved in the check.
To remove the special characters, we’ll create a simple extension function that is introduced in Scala 3:
extension (str: String) {
def sanitize: String = str.replaceAll("[^A-Za-z0-9]", "").toLowerCase
}
We’ll use this sanitize() method before starting the check for the following implementations.
3. Using reverse()
The simplest method to check for a palindrome string is by reversing the string and then comparing it against the input string:
def isPalindromeByReverse(str: String): Boolean = {
val sanitizedStr = str.sanitize
sanitizedStr == sanitizedStr.reverse
}
Before using the reverse() method and performing the comparisons, we eliminate any special characters using the sanitize() method created earlier.
4. Using Recursion
Another way to verify if a string is palindrome is by recursively comparing the characters from the front and back of the string repeatedly:
def isPalindromeByRecursion(str: String): Boolean = {
val sanitizedStr = str.sanitize
@tailrec
def isPalindromeRec(str: String): Boolean = {
str match {
case _ if str.length <= 1 => true
case _ if str.head == str.last => isPalindromeRec(str.tail.init)
case _ => false
}
}
isPalindromeRec(sanitizedStr)
}
In the above code, we implemented a tail-recursive isPalindromeRec() method to compare the characters recursively. After comparing the characters, the operation tail. init removes the string’s first and last characters and recursively invokes the same method with the remaining string.
5. Using zipWithIndex()
An alternate way to perform the palindrome check is by using the zipWithIndex() method:
def isPalindromeByForAll(str: String): Boolean = {
val sanitizedStr = str.sanitize
sanitizedStr.zipWithIndex.forall { case (ch, i) =>
ch == sanitizedStr.charAt(sanitizedStr.length - i - 1)
}
}
In this approach, we validate if the string is a palindrome by pairing each character with its corresponding index using the zipWithIndex() method. The pairs are then passed to the forall() method, where each pair confirms that the character at the current index matches its counterpart at the opposite end of the string.
6. Testing the Implementations
Now that we are ready with different implementations, let’s write unit tests to ensure they work correctly. We can utilize the ScalaTest along with ScalaCheck to execute detailed parameterized tests:
private val wordsTable = Table(
("Word", "Is Palindrome"),
("racecar", true),
("Madam", true),
("racecar!!", true),
("madam1", false),
("hello", false),
("10101", true)
)
it should s"check if a string is palindrome" in {
forAll(wordsTable) { (str, isPalindrome) =>
isPalindromeByReverse(str) shouldBe isPalindrome
}
}
We added the test for the isPalindromeByReverse() method. Similarly, we can add the tests for other implementations as well.
7. Conclusion
In this article, we discussed different ways to check whether a string is palindrome in Scala. Additionally, we covered the implementations with comprehensive tests.
As always, the sample code used here is available over on GitHub.