/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."
// and "Don't nod!". This version should even work with "cb�abc."
// (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;
}
}