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.
Related
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
Here's my code that I've written :
public String binary(String s)
{
String[] a = {
"0000","0001","0010","0011","0100","0101","0110","0111",
"1000","1001","1010","1011","1100","1101","1110","1111"
};
String k = "";
for(int i = 0; i <= s.length() - 1; i++)
{
if (s.charAt(i) == 'a') { k += a[10]; }
else if (s.charAt(i) == 'b') { k += a[11]; }
else if (s.charAt(i) == 'c') { k += a[12]; }
else if (s.charAt(i) == 'd') { k += a[13]; }
else if (s.charAt(i) == 'e') { k += a[14]; }
else if (s.charAt(i) == 'f') { k += a[15]; }
else { k += a[i]; }
}
return k;
}
I am getting output as a[0-9] = 0000. How can I fix this? What am I doing wrong?
The problem is with use of a[i]. It is a logical error. Because i is loop variable which indicates the current index in s String. But you are using it to indexing it in variable a. So, i variable is use incorrectly here.
Following is corrected (and a bit optimized) code. See it working here:
public class HexaDecimal
{
public String binary(String s)
{
String[] a= {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
String k="";
for(int i=0;i<s.length();i++)
{
char ch = Character.toUpperCase(s.charAt(i));
if(ch>='A' && ch <= 'F') k+= a[ch - 'A' + 10];
else k+= a[ch - '0'];
}
return k;
}
}
Replace k+=a[i]; with k+=a[s.charAt(i) - '0'];
You're using your string index loop variable as an index into a rather than the character at that location in the string.
You need to do - '0' to convert from unicode codepoint to the value it represents as an ASCII digit (which I assume you want to use here)
Your last else does the incorrect calculation. It does not take into consideration what is inputted, only the position. You want it to be
else {
k += a[s.charAt(i) - '0'];
}
There are easier ways to get the binary representation of hexadecimals, and you probably also want to check the input that it does not contain anything else than 0-9 or a-f.
You can change the for loop to this:
for(int i=0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c >= '0' && c <= '9') k += a[c - '0'];
else if (c >= 'a' && c <= 'f') k += a[c - 'a' + 10];
else if (c >= 'A' && c <= 'F') k += a[c - 'A' + 10];
else throw new InvalidArgumentException(s);
}
This is a lot simpler and self-explanatory, at least in my opinion. Handles digits, uppercase and lowercase letters, and fails in an expected way on bad input.
Basically I'm trying to have a few while loops check specific indices within a string. The first loop that validates the length of the refNum works fine. When it gets to the bigger set of while loops it just skips it and I'm not sure why, any feed back would be greatly appreciated.
package testing_code;
import java.util.Scanner;
/**
*
* #author A.Con
*/
public class Testing_Code
{
public static void main(String[] args)
{
Scanner userInput = new Scanner (System.in);
String refNum;
System.out.println("Enter refNum: example - WE123A");
refNum = userInput.next();
int rnLength = refNum.length();
while(rnLength < 6 || rnLength > 6)
{
System.out.println("Invalid reference number. Try again.\n ");
System.out.println("Please enter reference No.: ");
refNum = userInput.next();
rnLength = refNum.length();
}
while(!(refNum.charAt(0) >= 'A') && !(refNum.charAt(0) <= 'Z') && !(refNum.charAt(1) >= 'A') && !(refNum.charAt(1) <= 'Z'))
{
while(!(refNum.charAt(2) >= '0') && !(refNum.charAt(2) <= '9') && !(refNum.charAt(3) >= '0') && !(refNum.charAt(3) <= '9'))
{
while(!(refNum.charAt(4) >= '0') && !(refNum.charAt(4) <= '9') && !(refNum.charAt(5) >= 'A') && !(refNum.charAt(5) <= 'Z'))
{
System.out.println("Invalid reference number. Try again.\n ");
System.out.println("Please enter reference No.: ");
refNum = userInput.next();
}
}
}
Your while conditions are all wrong. !(refNum.charAt(0) >= 'A') && !(refNum.charAt(0) <= 'Z') for instance checks if a character is lower than A and higher than Z, which is impossible; you should be using or instead.
As a matter of fact, there are a lot of ways you can improve this. Here's my version
public class Testing_Code
{
static boolean inRange(char c, char first, char last) {
return (c >= first) && (c <= last);
}
public static void main(String[] args)
{
Scanner userInput = new Scanner (System.in);
String refNum;
System.out.println("Enter refNum: example - WE123A");
refNum = userInput.next();
while(refnum.length() != 6
|| !inRange(refnum.charAt(0), 'A', 'Z')
|| !inRange(refnum.charAt(1), 'A', 'Z')
|| !inRange(refnum.charAt(2), '0', '9')
|| !inRange(refnum.charAt(3), '0', '9')
|| !inRange(refnum.charAt(4), '0', '9')
|| !inRange(refnum.charAt(5), 'A', 'Z'))
{
System.out.println("Invalid reference number. Try again.\n ");
System.out.println("Please enter reference No.: ");
refNum = userInput.next();
rnLength = refNum.length();
}
}
}
First !(A >= B) is equivalent to (A < B). So !(refNum.charAt(0) >= 'A') && !(refNum.charAt(0) <= 'Z') is equivalent to (refNum.charAt(0) < 'A') && (refNum.charAt(0) > 'Z').
If you look at the ASCII table, you will see that "less than A and greater than Z" are mutually exclusive conditions. They will never both be true at the same time, so the while loop ends up simplifying to while(false)
Your condition while(!refNum.charAt(0) >= 'A') && !(refNum.charAt(0) <= 'Z')) is always false, as a char can't be less than 'A' and greater than 'Z' at same time. Use a || instead of && and you are good to go.
I will recommend using
Character.isLetter(refNum.charAt(0)) // returns true if the passed character is a letter
Character.isDigit(refNum.charAt(0)) // returns true, if the passed character is a digit.
Much simpler & easy to read.
I want to write a function to check if a given string in roman presentation is correct or not. They are a lot of cases of non allowed combinations : (I assume that the given string will represent a number between 1 and 3999)
We can't have the same character more than three times in a row : ex : IIII is false.
Some combinations are not allowed : DD is false ('D' + 'D' = 500 + 500 = 1000 which is M
We can't substract a character and add the same character just after : for example IXI is not correct event if IX is 9, it's not equal to 9 + 1
The most significant digits has to be at the beginning not at the middle or at the end. Ex : XM (for 1010) is false while MX is the correct one.
etc...
So, my idea was that rather than checking for the non allowed combinations, I will write ALL the possible allowed combinations and each time we meet a combination which is not among them, we will return false. That was my idea. The inconvenient is that my final function was very long and not really easy to understand.
For example, I wrote first a function to check for the thousands (if they exist of course), the function then returns the indexes that I will use to substring the current string to move to the next part (which will be hundreds in that case) :
private static int isThousandsValid(String str){
int len = str.length();
char a1 = str.charAt(0);
char a2 = (len >= 2)? str.charAt(1) : ' ';
char a3 = (len >= 3)? str.charAt(2) : ' ';
if (a1 == 'M' && a2 == 'M' && a3 == 'M') //if we met that combinatin
return 3; //we have to move after 3 digits to meet the beginning
//of the hundred digits
else if (a1 == 'M' && a2 == 'M') //same raisoning for other combinations
return 2;
else if (a1 == 'M')
return 1;
else if (a1 == 'D' || a1 == 'C' || a1 == 'L' || a1 == 'X' || a1 == 'V' || a1 == 'I' )
return 0;
else return -1;
}
Then, I wrote the same thing for hundreds, tens and units. Example for hundreds :
private static int isHundredsValid(String str){
if (str.isEmpty()) return 0;
int len = str.length();
char a1 = str.charAt(0);
char a2 = (len >= 2)? str.charAt(1) : ' ';
char a3 = (len >= 3)? str.charAt(2) : ' ';
char a4 = (len >= 4)? str.charAt(3) : ' ';
if (a1 == 'C' && a2 == 'M')
return 2;
else if (a1 == 'D' && a2 == 'C' && a3 == 'C' && a4 == 'C')
return 4;
else if (a1 == 'D' && a2 == 'C' && a3 == 'C')
return 3;
else if (a1 == 'D' && a2 == 'C')
return 2;
else if (a1 == 'D')
return 1;
else if (a1 == 'C' && a2 == 'D')
return 2;
else if (a1 == 'C' && a2 == 'C' && a3 == 'C')
return 3;
else if (a1 == 'C' && a2 == 'C')
return 2;
else if (a1 == 'C')
return 1;
else if (a1 == 'L' || a1 == 'X' || a1 == 'V' || a1 == 'I' )
return 0;
else return -1;
}
Then, in my final function, I write this :
public static boolean isValidRoman(String str){
str = str.trim(); //remove spaces
if (str.isEmpty()) return false;
int index1 = isThousandsValid(str);
String str1 = mySubstring(str, index1);
int index2 = isHundredsValid(str1);
String str2 = mySubstring(str1, index2);
int index3 = isTensValid(str2);
String str3 = mySubstring(str2, index3);
int index4 = isUnitsValid(str3);
String str4 = mySubstring(str3, index4);
if (str1.isEmpty() || str2.isEmpty() || str3.isEmpty())
return true;
if (index1 == -1 || index2 ==-1 || index3 == -1 || index4 == -1)
return false;
return str4.isEmpty(); //if we still have ANOTHER character after it terminates
}
Finally "mySubstring" is just a simple function that I used to refactor and clear my code :
private static String mySubstring(String str, int index){
if (index == -1 ) return str;
else
return str.substring(index);
}
I have please two main questions :
Does this function seem correct for you? I had tested in many examples but I'm not really sure (I can't test all the 3999 possible combinations...)
Is it possible to improve it? Just to make it cleaner or more readable?
Is there any easier way to check for the validity of roman number rather than write all those cases??
I would go for the short and crazy solution and match the string using a regular expression:
public boolean isRoman(String s)
{
return !s.isEmpty()
&& s.matches("M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})");
}
I want to write a program which receive a string value and print the decimal number.
In addition, if the string value is not 1 or 0, I need to print a message.
I wrote this code but it is always getting inside the if command.
I Would appreciate your support!
Thank you
import java.util.Random;
public class Decimal {
public static void main(String[] args) {
String input = (args[0]);
int sum = 0;
for (int i = 0; i <= input.length(); i++) {
if (!(input.charAt(i) == '0') || (input.charAt(i) == '1')) {
System.out.println("wrong string");
break;
}
char a = input.charAt(i);
if (a == '1') {
sum |= 0x01;
}
sum <<= 1;
sum >>= 1;
System.out.println(sum);
}
}
}
The ! (not) operator of the if statement only applies to the first part:
if ( ! (input.charAt(i) == '0')
||
(input.charAt(i) == '1')
) {
So that is the same as:
if ((input.charAt(i) != '0') || (input.charAt(i) == '1')) {
When you actually meant to do:
if (input.charAt(i) != '0' && input.charAt(i) != '1') {
It's a good thing though, because once that works, you're going to get an IndexOutOfBoundsException when i == input.length(). Change the loop to:
for (int i = 0; i < input.length(); i++) {
And for performance, move variable a up and use it in that first if statement. Rename to c or ch is more descriptive/common.
Doing both sum <<= 1 and sum >>= 1 leaves you where you started. Is that what you wanted? You should also do the left-shift before setting the right-most bit.
Applying all that, I believe you meant to do this:
String input = args[0];
int sum = 0;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c != '0' && c != '1') {
System.out.println("wrong string");
break;
}
sum <<= 1;
if (c == '1')
sum |= 1;
}
System.out.println(sum);