javacomputer-sciencedfaautomaton

Automaton DFA implementation not working using Java


I'm studying right now, at my university, DFA and NFA automatons and how to implement some of them using Java code.

I am having some trouble with this exercise: we have 4 different laboratory turns (T1, T2, T3 and T4) and we need to write code in order to recognize if a particular string (composed of the university badge number of a student and his name, e.g., 123321Johnson) corresponds to T2 or T3.

We know that:

We also know that the string has to be composed of at least one number and at least one letter.

E.g., the automaton has to accept "1232324Gac" or "1232323Lum" but not "121234Lum" or "121233Gac".

Here's the code I wrote:

import java.util.Scanner;

public class Es3 {

    static Scanner sc = new Scanner(System.in);
    String s = sc.next();
    public static boolean scan(String s)
    {
        int state = 0;                      
        int i = 0;                              

        while (state >= 0 && i < s.length()) {
            final char ch = s.charAt(i++);
            switch (state) {
            case 0:
                if (ch >= 0 && ch <= 9)
                    state = 1;
                else
                    state = -1;
                break;

            case 1:
                if (ch >=0 && ch <=9)
                    state = 1;
                else if (ch >='a' && ch <='k')
                    if ((s.charAt(i--))%2==0)
                        state = 2;
                    else
                        state = -1;
                else if (ch >='l' && ch <='z')
                    if ((s.charAt(i--))%2==1)
                        state = 3;
                    else
                        state = -1;
                else
                    state = -1;
                break;

            case 2:
                if (ch >='a' && ch <='z')
                    state = 2;
                else
                    state = -1;
                break;

            case 3:
                if (ch >='a' && ch <='z')
                    state = 3;
                else 
                    state = -1;
                break;
            }
        }
        return (state == 2 || state == 3);      
    }

    public static void main(String[] args)
    {
        System.out.println(scan(args[0]) ? "OK" : "NO");
    }
}

Obviously, the code is not working, but this is important to show the general purpose of the exercise.

Could someone help me?


Solution

  • The reason your algorithm wasn't working is because you were trying to compare char values to int values, which wouldn't give the anticipated result. Also, when you were checking if a char value was in a certain letter range, you didn't take capital letters into account.

    import java.util.Scanner;
    
    public class Es3 
    {
        static Scanner sc = new Scanner(System.in);
        String s = sc.next();
        public static boolean scan(String s)
        {
            int state = 0;
            int i = 0;
    
            while (state >= 0 && i < s.length()) {
                final char ch = s.charAt(i++);
                switch (state) {
                case 0:
                    // Compare the char to the char values of the numbers
                    if (ch >= '0' && ch <= '9')
                        state = 1;          
                    else
                        state = -1;
                    break;
    
                case 1:  
                    // Same here, compare the char to the char values of the numbers
                    if (ch >= '0' && ch <= '9')
                        state = 1;
                    // Check if the char is capital, as well as lowercase
                    else if ((ch >= 'a' && ch <= 'k') || (ch >= 'A' && ch <= 'K'))
                        // Convert the char to an int before performing the calculations
                        if ((Character.getNumericValue(s.charAt(i-1)))%2 == 0)
                            state = 2;
                        else
                            state = -1;
                    // Check if the char is capital as well
                    else if ((ch >= 'l' && ch <= 'z') || (ch >= 'L' && ch <= 'Z'))
                        // Convert from char to int before calculating
                        if ((Character.getNumericValue(s.charAt(i-1)))%2 == 1)
                            state = 3;
                        else
                            state = -1;
                    else
                        state = -1;
                    break;
    
                case 2:
                    // Check if the char is capital as well
                    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
                        state = 2;
                    else
                        state = -1;
                    break;
    
                case 3:
                    // Check if the char is capital as well
                    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
                        state = 3;
                    else 
                        state = -1;
                    break;
                }
            }
            System.out.println("State "+state);
            return (state == 2 || state == 3);      
        }
    
        public static void main(String[] args)
        {
            System.out.println(scan(args[0]) ? "OK" : "NO");
        }
    }
    

    I think the code above should do what you’re trying to do.