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: }