/** A class of static recursive functions on Strings. */
public class StringRecursion {
    // IN THIS LECTURE, all String parameters are not null.
    
    /** Yields" length of s */
    public static int len(String s) {
        //System.out.println("s is: \"" + s + "\"");
        if (s.isEmpty()) {
            return 0;
        }
        
        // { s has at least one character}
        return 1 + len(s.substring(1));
    }
    
    
    /** Yields: number of 'e's in s */
    public static int numEs(String s) {
        //System.out.println("s is: \"" + s + "\"");
        if (s.isEmpty()) {
            return 0;
        }

        // { s has at least one character}
        // return (number of 'e's in s[0]) + (number of 'e's in s[1..])
        return (s.charAt(0) == 'e' ? 1 : 0) + numEs(s.substring(1));
    }
    
    
    /** Yields: s but with blanks removed */
    public static String deblank(String s) {
        if (s.isEmpty()) {
            return s;
        }
        
        if (s.charAt(0) == ' ') {
            return deblank(s.substring(1));
        }
        
        return s.charAt(0) + deblank(s.substring(1));
    }
    
    
    /** Yields: s but with everything that is not a letter removed */
    public static String depunct(String s) {
        if (s.isEmpty()) {
            return s;
        }
        
        if (!Character.isLetter(s.charAt(0))) {
            return depunct(s.substring(1));
        }
        
        return s.charAt(0) + depunct(s.substring(1));
    }
    
    
    /** Yields: "the characters c and d differ only in case, if at all" */
    private static boolean equalIgnoreCase(char c, char d) {
        return Character.toUpperCase(c) == Character.toUpperCase(d);
    }
    
    
    
    /** Yields: "s is a palindrome"
     *  There are two ways to define a palindrome: 
     *  1. s is a palindrome if it reads the same backward and forward.
     *  2. s is a palindrome if either
     *     (1) its length is <= 1   OR
     *     (2) its first and last chars are the same and the string
     *         between them is a palindrome.
     *  Letters that differ only in case are considered to match. 
     */
    public static boolean isPal(String s) {
        //System.out.println("s is: \"" + s + "\"");
        if (s.length() < 2)
            return true;
        // { s has at least 2 characters }
        // return (first and last chars match) && (inner substring is pal.)
        return equalIgnoreCase(s.charAt(0), s.charAt(s.length()-1)) && 
            isPal(s.substring(1,s.length()-1));
    }
    
    
    /** Yields: "s is a palindrome" 
      * Comparison is not case-sensitive. */
    public static boolean isPal2(String s) {
        return s.equalsIgnoreCase(reverse(s));
    }
    
    
    /** Yields: "s is a palindrome if you pay attention only to the letters"
      * Case and any non-letter characters are ignored. */
    public static boolean isPalLoosely(String s) {
        return isPal(depunct(s));
    }
         
   
    /** Yields: s with its characters in reverse order */
    public static String reverse(String s) {
        if (s.length() < 2) {
            return s;
        }
        
        // { s has at least 2 chars }
        return reverse(s.substring(1)) + s.charAt(0);
    }
    
    
}