Search code examples
javastackqueuepalindrome

How can I write code that indicates the first position in the text input by the user violates the palindrome property?


Say I would input “Able were you ere you saw Elba”. This looks like a palindrome until you see the first “e” in “were”, so the output for this text would be : This is not a palindrome Mismatch detected at : Ablewe

Below is the driver

public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        String line;

        do {

            // prompt user for input String and store it in line
            System.out.print("Enter an expression (or hit Enter to exit) : ");
            line = input.nextLine();

            // convert input String to upper case
            line = line.toUpperCase();

            // if user hits Enter or simply types in spaces and hits enter, break out of loop
            if (line.trim().isEmpty()) {
                break;
            }

            // call isPalindrom
            // if it returns true, display one message, else display another
            if (Palindrome.isPalindrome(line)) {
                System.out.println("Your expression is a palindrome.");
            } else {
                System.out.println("Your expression is not a palindrome.");
            }

        } while (line.length() != 0);

        System.out.println("You didn't enter an expression.  Exiting application ...");
    }
}

Below is the class that has the isPalindrome method

 public static boolean isPalindrome(String input){
        
        // create Queue and Stack of Characters
        // to store the input String
        Queue<Character> q = new LinkedList<>();
        Stack<Character> s = new Stack();
        
        // temporarily store the individual Characters
        // in input String before they're pushed onto
        // Stack and added to Queue
        Character letter;
        
        // keep track of differences between Characters
        // in Stack and Queue
        int mismatches = 0;
        
        // loop through input String
        for (int i = 0; i < input.length(); i++){
            // get current Character
            letter = input.charAt(i);
            
            // if the current Character is an alphabetic character
            if (Character.isLetter(letter)){
                // push it onto the Stack
                s.push(letter);
                // add it to the Queue
                q.add(letter);
            }
        }
        
        // while the Queue isn't empty
        while (!q.isEmpty()){
            // remove a Character from the Queue
            // pop a Character from the Stack
            // if they're not equal, increment mismatches
            if (!q.remove().equals(s.pop()))
                // Stack will produce the input String backwards
                // Queue will produce the input String forwards
                mismatches++;
        }
        
        // return true if there are no mismatches, else return false
        return (mismatches == 0);
    }
}

I need the output to show where the mismatch occurs


Solution

    1. Create a string (allLetters in the code given below) by replacing all non-letters by empty string i.e. input.replaceAll("[^\\p{L}]", "") where ^\\p{L} specifies a non-letter character.
    2. Use a variable (index in the code given below) to track the position of letters which have been processed. When the mismatch is detected, print allLetters.substring(0, index + 1) and break the loop.

    Code:

    int index = 0;
    String allLetters = input.replaceAll("[^\\p{L}]", "");
    // while the Queue isn't empty
    while (!q.isEmpty()) {
        // remove a Character from the Queue
        // pop a Character from the Stack
        // if they're not equal, increment mismatches
        if (!q.remove().equals(s.pop())) {
            // Stack will produce the input String backwards
            // Queue will produce the input String forwards
            mismatches++;
            System.out.println("Mismatch detected at: " + allLetters.substring(0, index + 1));
            break;
        }
        index++;
    }
    

    A sample run:

    Enter an expression (or hit Enter to exit) : Able were you ere you saw Elba
    Mismatch detected at: ABLEWE
    Your expression is not a palindrome.
    Enter an expression (or hit Enter to exit) : 
    

    Note: Currently, you are passing the user input converted to the upper case to the function, isPalindrome and therefore the output string (ABLEWE in the sample run shown above) is in the upper case. A better place to change the case would be inside isPalindrome itself as shown below:

    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    import java.util.Stack;
    
    public class Palindrome {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            String line;
    
            do {
    
                // prompt user for input String and store it in line
                System.out.print("Enter an expression (or hit Enter to exit) : ");
                line = input.nextLine();
    
                // if user hits Enter or simply types in spaces and hits enter, break out of
                // loop
                if (line.trim().isEmpty()) {
                    break;
                }
    
                // call isPalindrom
                // if it returns true, display one message, else display another
                if (Palindrome.isPalindrome(line)) {
                    System.out.println("Your expression is a palindrome.");
                } else {
                    System.out.println("Your expression is not a palindrome.");
                }
    
            } while (line.length() != 0);
    
            System.out.println("You didn't enter an expression.  Exiting application ...");
        }
    
        public static boolean isPalindrome(String input) {
            // Create a string by replacing all non-letters by empty string
            String allLetters = input.replaceAll("[^\\p{L}]", "");
    
            // convert input String to upper case
            input = input.toUpperCase();
    
            // create Queue and Stack of Characters
            // to store the input String
            Queue<Character> q = new LinkedList<>();
            Stack<Character> s = new Stack();
    
            // temporarily store the individual Characters
            // in input String before they're pushed onto
            // Stack and added to Queue
            Character letter;
    
            // keep track of differences between Characters
            // in Stack and Queue
            int mismatches = 0;
    
            // loop through input String
            for (int i = 0; i < input.length(); i++) {
                // get current Character
                letter = input.charAt(i);
    
                // if the current Character is an alphabetic character
                if (Character.isLetter(letter)) {
                    // push it onto the Stack
                    s.push(letter);
                    // add it to the Queue
                    q.add(letter);
                }
            }
    
            int index = 0;
            // while the Queue isn't empty
            while (!q.isEmpty()) {
                // remove a Character from the Queue
                // pop a Character from the Stack
                // if they're not equal, increment mismatches
                if (!q.remove().equals(s.pop())) {
                    // Stack will produce the input String backwards
                    // Queue will produce the input String forwards
                    mismatches++;
                    System.out.println("Mismatch detected at: " + allLetters.substring(0, index + 1));
                    break;
                }
                index++;
            }
    
            // return true if there are no mismatches, else return false
            return (mismatches == 0);
        }
    }
    

    A sample run:

    Enter an expression (or hit Enter to exit) : Able were you ere you saw Elba
    Mismatch detected at: Ablewe
    Your expression is not a palindrome.
    Enter an expression (or hit Enter to exit) :