Palindrome2.java
Download Palindrome2.java
1: // This application checks the command line arguments to see if they
2: // form a palindrome: text that reads the same forward or backward.
3: // When checking, spaces and punctuation marks are ignored, and so
4: // is the case and accents of the text. Examples include "Never odd or even."
5: // and "Don't nod!". This version should even work with "cb�abc."
6: // (You can enter cap A with Diaeresis (the two dots) with ALT+0196.)
7: //
8: // Written 11/2010 by Wayne Pollock, Tampa Florida USA
9: // Modified 11/2013 by WP: replaced recursive, BMP text only version
10: // with iterative, full Unicode version.
11:
12: import java.text.*; // For Unicode text normalization and comparison
13: import java.util.Locale; // for Unicode text comparison
14:
15: class Palindrome2 {
16: public static void main ( String [] args ) {
17: StringBuilder sb = new StringBuilder();
18: for ( String word : args )
19: sb.append( word );
20:
21: System.out.println( isPalindrome( sb.toString() ) );
22: }
23:
24: // This version first normalizes a Unicode string, then sanitizes it,
25: // and then compares using proper Unicode methods. At the same
26: // time, the algorithm is changed from recursive to iterative.
27: // (Note that for this application, sanitizing the text was unnecessary.)
28: private static boolean isPalindrome ( String text ) {
29:
30: // Normalize the Unicode to NFKC, as per CERT IDS01-J:
31: text = Normalizer.normalize( text, Normalizer.Form.NFKC );
32:
33: // Next, replace any non-valid letters or digits with nothing.
34: // (As per CERT IDS11-J, they could be replaced with U+FFFD, but
35: // for this application, just stripping them out works best.)
36: text = text.replaceAll( "[^\\p{IsAlphabetic}\\p{Digit}]", "" );
37:
38: // Make a Collator for U.S. English, to perform Locale-sensitive, full
39: // Unicode String comparisons, while ignoring case and accents:
40: Collator usCollator = Collator.getInstance( Locale.US );
41: usCollator.setStrength( Collator.PRIMARY );
42:
43: // Create a BreakIterator, to walk through the String one Unicode
44: // character (code point) at a time (safer than using String.codePoint
45: // methods):
46: BreakIterator bi = BreakIterator.getCharacterInstance();
47: bi.setText( text );
48:
49: int left = bi.first(); // index of first character
50: int right = bi.last(); // index after last character
51: right = bi.preceding(right); // index of last character
52:
53: while ( left < right ) { // While there are more characters to check:
54: // Sadly, Collator only compares Strings, not characters, so
55: // this is a bit ugly; the code-points are converted to char[],
56: // which must then be converted to a Strings:
57: if ( 0 != usCollator.compare(
58: new String( Character.toChars(text.codePointAt(left)) ),
59: new String( Character.toChars(text.codePointAt(right)) )
60: )
61: )
62: return false;
63:
64: // The two ends are equal; now move left and right toward the middle:
65: left = bi.following(left);
66: right = bi.preceding(right);
67: }
68:
69: // If you get to here, the String is a palindrome:
70: return true;
71: }
72: }