/home/wpollock1/public_html/AJava/Palindrome2.java

// This application checks the command line arguments to see if they
// form a palindrome: text that reads the same forward or backward.
// When checking, spaces and punctuation marks are ignored, and so
// is the case and accents of the text.  Examples include "Never odd or even."

// (You can enter cap A with Diaeresis (the two dots) with ALT+0196.)
//
// Written 11/2010 by Wayne Pollock, Tampa Florida USA
// Modified 11/2013 by WP: replaced recursive, BMP text only version
//   with iterative, full Unicode version.

import java.text.*;  // For Unicode text normalization and comparison
import java.util.Locale; // for Unicode text comparison

class Palindrome2 {
   public static void main ( String [] args ) {
      StringBuilder sb = new StringBuilder();
      for ( String word : args )
         sb.append( word );

      System.out.println( isPalindrome( sb.toString() ) );
   }

   // This version first normalizes a Unicode string, then sanitizes it,
   // and then compares using proper Unicode  methods.  At the same
   // time, the algorithm is changed from recursive to iterative.
   // (Note that for this application, sanitizing the text was unnecessary.)
   private static boolean isPalindrome ( String text ) {

      // Normalize the Unicode to NFKC, as per CERT IDS01-J:
      text = Normalizer.normalize( text, Normalizer.Form.NFKC );

      // Next, replace any non-valid letters or digits with nothing.
      // (As per CERT IDS11-J, they could be replaced with U+FFFD, but
      // for this application, just stripping them out works best.)
      text = text.replaceAll( "[^\\p{IsAlphabetic}\\p{Digit}]", "" );

      // Make a Collator for U.S. English, to perform Locale-sensitive, full
      // Unicode String comparisons, while ignoring case and accents:
      Collator usCollator = Collator.getInstance( Locale.US );
      usCollator.setStrength( Collator.PRIMARY );

      // Create a BreakIterator, to walk through the String one Unicode
      // character (code point) at a time (safer than using String.codePoint
      // methods):
      BreakIterator bi = BreakIterator.getCharacterInstance();
      bi.setText( text );

      int left = bi.first();  // index of first character
      int right = bi.last();  // index after last character
      right = bi.preceding(right);  // index of last character

      while ( left < right ) {  // While there are more characters to check:
         // Sadly, Collator only compares Strings, not characters, so
         // this is a bit ugly; the code-points are converted to char[],
         // which must then be converted to a Strings:
         if ( 0 != usCollator.compare(
                  new String( Character.toChars(text.codePointAt(left)) ),
                  new String( Character.toChars(text.codePointAt(right)) )
               )
            )
            return false;

         // The two ends are equal; now move left and right toward the middle:
         left = bi.following(left);
         right = bi.preceding(right);
      }

      // If you get to here, the String is a palindrome:
      return true;
   }
}