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})");
}
Related
The examples look like this, Input : "a-(b+c)" output "a-b-c", Input : "a-(a+b)" output "b"
I came up with this method, but the result for input: "a-(a+b)" is "a-a-b", which the correct one should be "b", how to improve that?
public String simplify(String str)
{
int len = str.length();
char res[] = new char[len];
int index = 0, i = 0;
Stack<Integer> s = new Stack<Integer> ();
s.push(0);
while (i < len) {
if (str.charAt(i) == '+') {
if (s.peek() == 1)
res[index++] = '-';
// If top is 0, append the same operator
if (s.peek() == 0)
res[index++] = '+';
} else if (str.charAt(i) == '-') {
if (s.peek() == 1)
res[index++] = '+';
else if (s.peek() == 0)
res[index++] = '-';
} else if (str.charAt(i) == '(' && i > 0) {
if (str.charAt(i - 1) == '-') {
// x is opposite to the top of stack
int x = (s.peek() == 1) ? 0 : 1;
s.push(x);
}
else if (str.charAt(i - 1) == '+')
s.push(s.peek());
}
else if (str.charAt(i) == ')')
s.pop();
else
res[index++] = str.charAt(i);
i++;
}
return new String(res);
}
import java.util.Scanner;
import javax.lang.model.util.ElementScanner14;
class mudit {
public static void main(final String[] args) {
final Scanner input = new Scanner(System.in);
System.out.print("Enter!!!");
final char n = input.next().charAt(0);
art :
if ((n >= 'a' && n <= 'z' ) || (n >= 'A' && n <= 'z'))
System.out.println(n + " is an alphabet.");
dart :
if ( n == 'a' || n == 'e' || n == 'i' || n == 'o' || n == 'u' || n == 'A' || n == 'E' || n == 'I' || n == 'O' || n == 'U')
System.out.println("VOWEL");
break dart;
else
System.out.println("CONSONANT");
break dart;
else if ( n * 1 == n)
System.out.println(n + " is a numerical value.");
else
System.out.println("Something else");
input.close();
}
}
When ever i run this code i run into an error.
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Syntax error on token "else", delete this token
at mudit.main(mudd.java:28)
I want it to tell whether the entered charachter is an alphabet(vowel or consonant) or numerical
I am using vs code editor.
The problem is that the if statement block is more than one line. You can only use an if statement, else statement, or else if statement without curly braces if the block is only a single line. To fix this problem, simply wrap your conditions in curly braces.
On another note, breaking in this context doesn't do anything. You can only break out of a for-loop, advanced for-loop, while loop, do-while loop, and switch statement. I may have forgotten 1 or 2 scenarios so feel free to remind me!
If there is more then one line inside a "if" or "else" you need to enclose those statements with { }. This should work now.
import java.util.Scanner;
import javax.lang.model.util.ElementScanner14;
class mudit {
public static void main(final String[] args) {
final Scanner input = new Scanner(System.in);
System.out.print("Enter!!!");
final char n = input.next().charAt(0);
art :
if ((n >= 'a' && n <= 'z' ) || (n >= 'A' && n <= 'z')) {
System.out.println(n + " is an alphabet.");
dart :
if ( n == 'a' || n == 'e' || n == 'i' || n == 'o' || n == 'u' || n == 'A' || n == 'E' || n == 'I' || n == 'O' || n == 'U') {
System.out.println("VOWEL");
break dart;
} else {
System.out.println("CONSONANT");
break dart;
}
}
else if ( n * 1 == n)
System.out.println(n + " is a numerical value.");
else
System.out.println("Something else");
input.close();
}
}
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.
Hello guys im trying to make a calculator that is based on user scanner input, The calculator works fine for calculating from left to right but im having difficulties putting priorities in *,/ and ()
for example 3+(5*2)+1 should be 14 instead mine is 17, and then when i tried
5+((2+1)*3)-1 it gives me weird error..
Can anyone help please? and how can i make my code appear more efficient and simpler thank you in advance.
So here is my code :
System.out.print("Input Equation : ");
n = s.next() + s.nextLine();
n = n.replaceAll("\\s+", "");
char[] nans = n.toCharArray();
c = 0;
for (int i = 0; i < n.length(); i++)
if (nans[i] == '+' || nans[i] == '-' || nans[i] == '/' || nans[i] == '*')
c++;
char[] op = new char[c];
int[] num = new int[c + 1];
c = 0;
for (int i = 0; i < n.length(); i++) {
if (nans[i] == '+' || nans[i] == '-' || nans[i] == '/' || nans[i] == '*') {
op[c] = nans[i];
c++;
}
}
c = 0;
for (int i = 0; i < n.length(); i++) {
if (nans[i] == '1' || nans[i] == '2' || nans[i] == '3' || nans[i] == '4' || nans[i] == '5'
|| nans[i] == '6' || nans[i] == '7' || nans[i] == '8' || nans[i] == '9' || nans[i] == '0')
nus = nus + nans[i];
else if (nans[i] == '+' || nans[i] == '-' || nans[i] == '/' || nans[i] == '*') {
num[c] = Integer.parseInt(nus);
nus = "";
c++;
}
if (i == n.length() - 1){
num[c] = Integer.parseInt(nus);
}
}
for (int i = 0; i < c; i++) {
if (op[i] == '+') {
result = result + num[i] + num[i + 1];
num[i + 1] = 0;
}
else if (op[i] == '-') {
result = result + num[i] - num[i + 1];
num[i + 1] = 0;
}
else if (op[i] == '/') {
result = (result + num[i]) / num[i + 1];
num[i + 1] = 0;
}
else if (op[i] == '*') {
result = (result + num[i]) * num[i + 1];
num[i + 1] = 0;
}
}
System.out.print(" = "+ result);
When you read a token (that is an argument for operator or simply a number), make sure that the next operator is not multiplication or division, otherwise, you want to calculate that one. You can achieve this by means of recursion easily.
for my compsci assignment we're supposed to take a string given to us with integers and letters in it, then create a method that takes that string and converts it into an integer array with the integers in it. For some reason my method is not adding ints to the array, I'm not sure why.
For the LETTERS given in the string, we're supposed to discard them, so we have an array with ONLY int values; ex. input: abs3131afas312 the array would have {3131,312}
This is the link to the assignment.
Here's my method:
public static int[] intParse(String a){
int[] array1 = new int[a.length()];
int b = 0;
for(int i = 0; i < a.length(); ++i)
{
int g = a.charAt(i);
if(g == 1 || g == 2 || g == 3 || g == 4 || g == 5 || g == 6 || g == 7 || g == 8 || g == 9 || g == 0)
{
String c;
for(int j = i; j < a.length(); ++j)
{
int k = a.charAt(j);
if(k != 1 && k != 2 && k != 3 && k != 4 && k != 5 && k != 6 && k != 7 && k != 8 && k != 9 && k != 0)
{
c = a.substring(j,k-1);
array1[b] += Integer.parseInt(c);
b++;
j = (a.length());
i = a.charAt(j);
}
else
{
c = a.substring(j,a.length());
array1[b] = Integer.parseInt(c);
j = a.length();
}
}
}
}
return array1;
}
Rather than comparing your characters to integers and using Integer.parseInt, you should be using the following very useful utility methods:
Character.isDigit(int codepoint)
Character.getNumericValue(int codepoint)
Also, your logic seems a little sketchy. When k is a digit code point, you are trying to parse the entire rest of the string. That doesn't seem consistent with what you're trying to do with the outer loop.
First of all, a is a string, and contains ASCII characters not integers. Character '1' is not equal to the integer 1. It is equal to the ASCII value of '1' which happens to be 49.
So first thing you should do is change that long if condition to:
char c = a.charAt(i);
if (c >= '0' && c <='9')
{
...
}
What you should do then is keep a string (a new string each time you encounter a non-numeric character and then a numeric character, and keep appending c to it until the character you find is non-numeric.
Then you can simply do Integer.parseInt(yourString) to get the number in an integer.
a fix for you:
char g = a.charAt(i);
if(g == '1' || g == '2' || g == '3' || g == '4' || g == '5' || g == '6' || g == '7' || g == '8' || g == '9' || g == '0') {
or much nicer:
char g = a.charAt(i);
if(g >= '0' && g <= '9') {
Your other if needs to be fixed, too
char k = a.charAt(j);
if(k < '0' || k > '9') {
You might prefer this approach:
Scanner sc = new Scanner("abs3131afas312");
String match;
while ((match = sc.findInLine("(\\d+)"))!=null) {
// instead of printing it, put it in your array
// or a list (and then convert to array)
System.out.println(Integer.parseInt(match));
}
sc.close();
Output:
3131
312