How to implement a DFA which recognizes comments? - java

I'd need some help with Java here...
I have to implement a DFA in Java that recognizes Java comments contained between /* and */.
In order to start with simple things, let's say that DFA's alphabet is: {'/', '*', 'a'}, so it recognizes only those 3 elements.
Possible accepted Strings:
1) /**/
2) /****/
3) /*a*a**/
4) /*a**/
It won't accept:
1) /*/
2) /**/***/
In order to achieve that I developed this method:
public static boolean scan(String s){
int i = 0, state = 0;
while(i < s.length() && stato >= 0){
final char ch = s.charAt(i++);
switch(state){
case 0:
if(ch == '/')
state = 1;
else
state = -1;
break;
case 1:
if(ch == '*')
state = 2;
else
state = -1;
break;
case 2:
if(ch == 'a')
state = 2;
else if(ch == '/')
state = 3;
else
state = -1;
break;
case 3:
if(ch == '*')
state = 4;
else
state = -1;
break;
case 4:
if(ch == ' ')
state = 4;
else
state = -1;
break;
}
}
System.out.println("State: " + state);
return state == 4;
}
But with simplest input /**/ status variable is -1, when it should be 4.
Which changes should I make?
Hope you guys can help me...
Thank you

In Step 3 your state became -1. then how you get matching.
See this block:
case 2:
if(ch == 'a')
state = 2;
else if(ch == '/')
state = 3;
else
state = -1;
break;
State 0 : char / : nextState 1
State 1 : char * : nextState 2
State 2 : char * : nextState -1
State -1 : char / : nextState -1

Related

how to convert this code into the switch statement [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
i want to know how could i can this code into the switch statement
i want to do this if else statement into the switch statement please help me out to find out what i have to do for changing this code into switch statement.
if (board[r - 1][c] == ' ' && board[r][c - 1] == ' ') {
nextRow = r;
nextCol = c - 1;`enter code here`
return true;
}
// We will try to move the cell up.
if (board[r - 1][c] == ' ') {
nextRow = r - 1;
nextCol = c;
return true;
}
// We will try to move the cell to the right.
else if (board[r][c + 1] == ' ') {
nextRow = r;
nextCol = c + 1;
return true;
}
// We will try to move the cell to the left.
else if (board[r][c - 1] == ' ') {
nextRow = r;
nextCol = c - 1;
return true;
}
// We will try to move the cell down.
else if (board[r + 1][c] == ' ') {
nextRow = r + 1;
nextCol = c;
return true;
}
System.out.println("Error due to Array Bound Index");
return false;
}
You can't convert it to a switch, because you aren't picking what to do on the basis of a single value, and your conditions are not mutually exclusive.
However, you can convert the four ifs into a loop:
for (int a = 0; a < 4; ++a) {
int dr = (a & 1 == 0) ? 0 : (a & 2 == 0) ? 1 : -1;
int dc = (a & 2 == 0) ? 0 : (a & 1 == 0) ? 1 : -1;
if (board[r + dr][c + dc] == ' ') {
nextRow = r + dr;
nextCol = c + dc;
return true;
}
}
It seems you are not checking the same value with each if-else, so it would not be possible to write with a switch. A switch statement checks one variable to see if it fits given values.
Here is the switch statement documentation for more info https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
You can't convert this to switch statement because you don't check one value. For switch statements code must be like this:
int a = 0;
if (a == 0) {
...
}
else if (a == 1) {
...
}
else if (a == 2) {
...
}
...
and switch statement:
switch (a) {
case 0:
...
break;
case 1:
...
break;
case 2:
...
break;
}

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:
T1 is the turn of the ones who have an odd badge number and surname between "A" and "K"
T2 is the turn of even badge numbers and surnames between "A" and "K"
T3 is the turn of odd badge numbers and surnames between "L" and "Z"
T4 is the turn of even badge numbers and surnames between "L" and "Z"
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?
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.

how to assign a char to an variable on the base of the size of an ArrayList in Java?

I try to make an long if-statement more compact; this is how it is originaly:
char x;
if(list.size()== 1){
x = 'a';
}
if(list.size()== 2){
x = 'b';
}
if(list.size() == 3){
x = 'c';
}
if(list.size() == 4){
x= 'd';
}
Is there a possibility to compact this code?
thanks already,
Jari Van M
As a first step, we refactor the code to an if-else cascade and backup the list size we are going to use often:
1:
int size = list.size();
char x;
if(size == 1) {
x = 'a';
} else if(size == 2) {
x = 'b';
} else if(size == 3) {
x = 'c';
} else if(size == 4) {
x = 'd';
} else {
//undefined
x = '\0';
}
As we compare the list size with constants only in this case, we can further transform this into a switch statement:
2:
char x;
switch (list.size()) {
case 1: x = 'a'; break;
case 2: x = 'b'; break;
case 3: x = 'c'; break;
case 4: x = 'd'; break;
//undefined
default: x = '\0'; break;
}
Assuming this isn't a randomly chosen example but real code, we see that we need a function which takes a number starting from 1 which outputs the alphabet ('a' to 'z') with increasing value:
3:
char x;
if(list.isEmpty()) {
//undefined
x = '\0';
} else {
//our function
x = (char) ('a' + list.size() - 1);
if(x > 'z') {
//undefined
x = '\0';
}
}
You are basically mapping the size to a character. It can be done easier:
x = 'a' + list.size() - 1;
Easier Option:
Use switch case.
Tricker Option:
char x = (char) ('a' + list.size() - 1);
char x;
int size = list.size();
if (size >= 1 && size <= 4) {
x = "zabcd".charAt(size);
}

Evaluate arithmetic expression recursively

I need help with evaluating arithmetic expression (INFIX) via recursion. I made a tree, scanning from right to left (+,- first, *,/ second). The error is:
For input string: "2+3"
I don't what I'm doing wrong. I was hoping if someone can look at my method and point me to right direction please. Appreciate the help. Here is my method.
// recursive method to evaluate an expression given by string s
int evaluateE(String s)
{
String r1;
String r2;
int result = 0;
int i;
for(i = s.length() - 1; i >= 0; i--)
{
if (s.charAt(i) == '+' || s.charAt(i) == '-')
break;
else if (s.charAt(i) == '*' || s.charAt(i) == '/')
break;
}
r1 = s.substring(0, i);
r2 = s.substring(i + 1, s.length());
//Base case
if(!r1.contains("+") && !r1.contains("-") && !r1.contains("*") && !r1.contains("/") &&
!r2.contains("+") && !r2.contains("-") && !r2.contains("*") && !r2.contains("/"))
return Integer.parseInt(s);
switch (s.charAt(i))
{
case '+':
result = evaluateE(r1) + evaluateE(r2);
break;
case '-':
result = evaluateE(r1) - evaluateE(r2);
break;
case '*':
result = evaluateE(r1) * evaluateE(r2);
break;
case '/':
if (Integer.parseInt(r2) == 0) //if denominator is zero
{
System.out.println("Invalid divisor");
System.exit(1);
}
else
result = evaluateE(r1) / evaluateE(r2);
break;
}
return result;
}
You're checking the operators, if they contain an operator, i.e. for r1+r2 you check, if r1 or r2 contain a operator. If your String contains exactly 1 operator, neither r1 nor r2 contain a operator and therefore Integer.parse(s) will be executed. Since s = r1 + operator + r2 contains the operator, Integer.parse will throw an error.
To fix this, check the base case before doing anything else in that method:
int evaluateE(String s) {
//Base case
if (!s.contains("+") && !s.contains("-") && !s.contains("*") && !s.contains("/")) {
return Integer.parseInt(s);
}
int i;
for (i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '+' || s.charAt(i) == '-') {
break;
} else if (s.charAt(i) == '*' || s.charAt(i) == '/') {
break;
}
}
String r1 = s.substring(0, i);
String r2 = s.substring(i + 1, s.length());
int result = 0;
switch (s.charAt(i)) {
case '+':
result = evaluateE(r1) + evaluateE(r2);
break;
case '-':
result = evaluateE(r1) - evaluateE(r2);
break;
case '*':
result = evaluateE(r1) * evaluateE(r2);
break;
case '/':
int right = evaluateE(r2);
if (right == 0) //if denominator is zero
{
System.out.println("Invalid divisor");
System.exit(1);
} else {
result = evaluateE(r1) / right;
}
break;
}
return result;
}
That ignores operator precedence however, i.e. it evaluates expressions from left to right. E.g. 10-3*6/9+4 is interpreted as (((10-3)*6)/9)+4.
If you want to take operator precedence into accout, you have to ignore * or /, if there is a + or a - in the string. This would require you to modify your for loop:
// search for '+' and '-' first
for (i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '+' || s.charAt(i) == '-') {
break;
}
}
if (i < 0) {
// if '+' and '-' were not found, search for '*' and '/'
for (i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '*' || s.charAt(i) == '/') {
break;
}
}
}
It is not clear why you are returning Integer.parseInt(s) when in all likelihood s will have an operator (+,-,* or /). So, essentially you are trying to convert "2+3" into an int, which is the reason for the error.

If else statement not checking all the else statements

SO im making a program the will solve a maze recursively and im having problems with my
if else statements. I had a similar problem in a different part of my code and i solved it by just taking out all the else's and just having a bunch of if statements. But now i need it the stop searching after it finds the correct way to go.
public static void solveMaze(int ROW, int COL){
int isFinished = 0;
//ROW COL
//set up base case. find end if possible to get in 1 move then end
if(drawArray[ROW][COL+1] == ' '){
if(drawArray[ROW][COL+2] == 'E'){
isFinished = 1;
move(ROW,COL,ROW,COL+2);
}
}
if(drawArray[ROW][COL-1] == ' '){
if(drawArray[ROW][COL-2] == 'E'){
isFinished = 1;
move(ROW,COL,ROW,COL-2);
}
}
if(drawArray[ROW+1][COL] == ' '){
if(drawArray[ROW+2][COL] == 'E'){
isFinished = 1;
move(ROW,COL,ROW+2,COL);
}
}
if(drawArray[ROW-1][COL] == ' '){
if(drawArray[ROW-2][COL] == 'E'){
isFinished = 1;
move(ROW,COL,ROW-2,COL);
}
}
//find first open cell and choose it
int foundOpen = 0;
if(isFinished == 0){
if(drawArray[ROW][COL+1] == ' ' && drawArray[ROW][COL+2] != '*'){
drawArray[ROW][COL+2] = '*';
prevCol = COL;
prevRow = ROW;
COL+= 2;
foundOpen = 1;
}
else if(drawArray[ROW+1][COL] == ' ' && drawArray[ROW+2][COL] != '*'){
drawArray[ROW+2][COL] = '*';
prevCol = COL;
prevRow = ROW;
ROW+= 2;
foundOpen = 1;
}
else if(drawArray[ROW][COL-1] == ' ' && drawArray[ROW][COL-2] != '*'){
drawArray[ROW][COL-2] = '*';
prevCol = COL;
prevRow = ROW;
ROW-= 2;
foundOpen = 1;
}
else if(drawArray[ROW-1][COL] == ' ' && drawArray[ROW-2][COL] != '*'){
drawArray[ROW-2][COL] = '*';
prevCol = COL;
prevRow = ROW;
ROW-= 2;
foundOpen = 1;
}
}
//i have two recursive voids so this is chosing between them
if(foundOpen == 1){
move(prevRow,prevCol,ROW,COL);
solveMaze(ROW,COL);}
else if (foundOpen == 0 && isFinished == 0)
wrongChoice(ROW, COL);
}
SO basically this part of the program checks to see first if the end is near and if it is basically finish. I use to have if else statements for the first part to but i wouldnt work and the only way i could fix it was by taking out the else's. So in one maze that i have to solve the first move should be COL-1 == ' ' and COL-2 != '*'. so that if statement should happen but it doesnt. I put in a bunch of println statements to check where it was going off and isFInished == 0 so it starts into that if statement but then something goes wrong and nothing solution is found so wrongChoice is called. Im prety new to java and recursion so i might be missing something obvios.
boolean isFinished = true;
if (drawArray[ROW][COL+1] == ' ' && drawArray[ROW][COL+2] == 'E') {
move(ROW,COL,ROW,COL+2);
} else if (drawArray[ROW][COL-1] == ' ' && drawArray[ROW][COL-2] == 'E') {
move(ROW,COL,ROW,COL-2);
} else if (drawArray[ROW+1][COL] == ' ' && drawArray[ROW+2][COL] == 'E') {
move(ROW,COL,ROW+2,COL);
} else if (drawArray[ROW-1][COL] == ' ' && drawArray[ROW-2][COL] == 'E') {
move(ROW,COL,ROW-2,COL);
} else {
isFinished = false;
}
int foundOpen = 0;
if (!isFinished) {
That should do.
If you do this kind of looking at naybors more often:
static final int[][] naybors = {
{ 0, 1 },
{ 0, -1 },
{ 1, 0 },
{ -1, 0 },
};
boolean isFinished = false;
for (int[] nb : naybors) {
if (drawArray[ROW + nb[0]][COL + nb[1]] == ' '
&& drawArray[ROW + 2*nb[0]][COL + 2*nb[1]] == 'E') {
move(ROW, COL, ROW + 2*nb[0], COL + 2*nb[1);
isFinished = true;
break;
}
}
Also saw:
else if(drawArray[ROW][COL-1] == ' ' && drawArray[ROW][COL-2] != '*'){
drawArray[ROW][COL-2] = '*';
prevCol = COL;
prevRow = ROW;
//Wrong: ROW-= 2;
COL -= 2; // Good?
foundOpen = 1;
}
you could System.out.print and check where you want it to stop then use #mserioli suggestion which will work. good luck

Categories