Finding a Palindrome - ISerializable - Roy Osherove's Blog

Finding a Palindrome

[Update: I added a third variation of this which solves all the problems mentioned in the comments. Was really fun - used a single line of regular expressions and it worked like a charm!]
 
It got me intrigued - so here's my answer to finding a palindrome (a string you can read forward and backward the same):
 

[Test]

   public void TestPelindromSimple()

   {

         Assert.IsTrue(IsPalindrome("a"),"a");

         Assert.IsFalse(IsPalindrome("ab"),"ab");

         Assert.IsTrue(IsPalindrome("aba"),"aba");

         Assert.IsFalse(IsPalindrome("abc"),"abc");

 

         Assert.IsTrue(IsPalindrome("abba"),"abba");

         Assert.IsFalse(IsPalindrome("abbc"),"abbc");

 

         Assert.IsTrue(IsPalindrome("abcba"),"abcba");

         Assert.IsFalse(IsPalindrome("abcbc"),"abcbc");

 

         Assert.IsTrue(IsPalindrome("lelelel"),"lelelel");

         Assert.IsFalse(IsPalindrome("lele4el"),"lele4el");

 

         Assert.IsFalse(IsPalindrome(null),"null");

         Assert.IsTrue(IsPalindrome("ABba"),"ABba");

 

   }

 

 

 

   private bool IsPalindrome(string text)

   {

         if(text==null)

         {

               return false;

         }

         if(text.Length==1)

         {

               return true;

         }

 

         text=text.ToLower();

         int firsthalfIndex = (text.Length/2);

         int secondHalfIndex= (text.Length/2);

 

         if(text.Length%2!=0)

         {

               secondHalfIndex+=1;

         }

         char[] part1 = text.Substring(0,firsthalfIndex).ToCharArray();

         char[] part2 = text.Substring(secondHalfIndex).ToCharArray();

         Array.Reverse(part2);

              

         return (new string( part1)== new string(part2));

   }

 

I liked what I had but then it occurred to me: all these test can pass with this simple routine:

private bool IsPalindrome(string text)

 {

   if(text==null)

   {

      return false;

   }

  

   text=text.ToLower();

   char[] backwards = text.ToCharArray();

   Array.Reverse(backwards);

          

   return (new string( backwards)== text);

 }

 

 

Ain't life funny?

 

[Update]

This variation adds a single line of regex to comply with the dictionary form of Palindrome.

I also added a couple of unit tests to make sure it works:

 

Assert.IsTrue(IsPalindrome("ab cb a"),"ab cb a");

Assert.IsTrue(IsPalindrome("A man, a plan, a canal, Panama!"),"A man, a plan, a canal, Panama!");

 

private bool IsPalindrome(string text)

{

   if(text==null){

      return false;

   }

 

  text=text.ToLower();

  //remove whitespace and other non numeric chars

  text = Regex.Replace(text,@"[\s\W]",string.Empty);

  char[] backwards = text.ToCharArray();

  Array.Reverse(backwards);

                       

  return (new string( backwards)== text);

}

 

Published Thursday, September 16, 2004 5:01 AM by RoyOsherove
Filed under:

Comments

Wednesday, September 15, 2004 11:07 PM by Jonathan Cogley

# re: Finding a Palindrome

Nice refactoring! :-)

As a TDDer, expressing the rules with Asserts just makes so much sense - nice to see others think the same!

I have always thought of palindromes as being more loose, such as:

Madam I'm Adam

Although I guess this would simply require same-casing everything and removing whitespace and punctuation ...
Thursday, September 16, 2004 12:28 AM by Richard Tallent

# re: Finding a Palindrome

Uhm, how about this?

private bool IsPalindrome(string text)
{
if(text==null) return false;
text=text.ToLower();
string backwards=Microsoft.VisualBasic.StrReverse(text);
return (backwards==text);
}
Thursday, September 16, 2004 5:16 AM by Ross

# re: Finding a Palindrome


"X" == "X" ? Or "X".Equals( "X" ) ?
Thursday, September 16, 2004 12:14 PM by James Snape

# re: Finding a Palindrome

Just one thing... A palindrome is (from dictionary.com) "A word, phrase, verse, or sentence that reads the same backward or forward For example: 'A man, a plan, a canal, Panama!'".

I don't think that passes.

James,
Thursday, September 16, 2004 2:33 PM by Mani Swaminathan

# re: Finding a Palindrome

As per the original algorithm
just modifying a little, i like the idea of going half way than using string operations which are expensive

char[] a = text.ToCharArray();
bool b = true;
int l = a.length;
int i =0;
while ( b && i < l/2 )
{
if ( !(a[i] == a[l-i-1]) ) b=false;
i++;
}
return b;

Saturday, September 18, 2004 11:35 AM by Dan Golick

# re: Finding a Palindrome

You should probably get rid of white space first. Generally people don't consider white space in palindromes.
Sunday, September 19, 2004 1:28 PM by Able was I, ere I saw Elba

# re: Finding a Palindrome

Mani's solution is good, but why create a character array unnecessarily, and why keep looping when you've established they're different? The string class already has an indexer so you can do:
if (text[i] == test[l-i-1])

You could generalize it to ignore whitespace and punctuation (air code) ...

int firstIndex = 0;
int lastIndex = text.Length-1;
while(firstIndex < lastIndex)
{
// Ignore punctuation and whitespace
if (Char.IsPunctuation(text[firstIndex]) || Char.IsWhiteSpace(text[firstIndex]))
{
firstIndex++;
continue;
}
if (Char.IsPunctuation(text[lastIndex]) || Char.IsWhiteSpace(text[lastIndex]))
{
lastIndex--;
continue;
}
if (Char.ToLower(text[firstIndex]) != Char.ToLower(text[lastIndex])) return false;
firstIndex++;
lastIndex--;
}
return true;

Monday, September 20, 2004 2:22 AM by TrackBack

# Palindrome Finding Algorithms