Recursion Question: A formula is defined as a string
containing positive single digits numbers, variables, and operations
(such that: +,-,/,*,%). In addition, the string doesn't contain space
bars. Each operation between two numbers or variables is separated
with brackets - "()".
Valid formulas would be: ((6+x)*(4+2)), (((9*4)+(x+8))*(6-5)), 6,
(3+1), etc...
Invalid formulas would be: -6, (1+*(x+2)*(1-6)), ( (6+x)), 10,
2+x, (33+3), ((1+2)), etc...
Write a boolean recursion function which gets a string - "s" and
returns true if he is a valid formula, and false otherwise.
The code has to be written via java.
My attempt: I have tried the following, putting in mind that the number of "(" is less equal to the number of ")", however, it doesn't right since: "((1+2))" isn't a valid formula. So I have written the following:
public static boolean isFormula(String s) {
return calc(s, 0, 0, 0, 0);
}
public static boolean calc(String s, int oc, int l, int r, int g) {
if (s == "") {
return (oc <= 1 && (l == r));
}
char c = s.charAt(0);
char e = s.charAt(s.length() - 1);
if (g == 0) {
if (!(op(s))) return false;
else {
return calc(s, oc, l, r, g + 1);
}
}
if (c == '(') {
return calc(s.substring(1), oc, l + 1, r, g);
} else if (c == ')') {
return calc(s.substring(1), oc, l, r + 1, g);
} else if ((c >= '0' && c <= '9') || c == 'x') {
if (oc <= 1) {
return calc(s.substring(1), 0, l, r, g);
}
} else if ((c == '+' || c == '-' || c == '*' || c == '/')) {
return calc(s.substring(1), oc + 1, l, r, g);
}
return false;
}
public static boolean op(String s) {
int count = 0;
if (s.charAt(0) == '+' || s.charAt(0) == '-' || s.charAt(0) == '*' || s.charAt(0) == '/') {
count++;
}
String d = s.replace("(", "");
if (d.charAt(0) == '+' || d.charAt(0) == '-' || d.charAt(0) == '*' || d.charAt(0) == '/') {
count++;
}
d = d.replace(")", "");
d = d.replace("+", ",");
d = d.replace("-", ",");
d = d.replace("*", ",");
d = d.replace("/", ",");
String[] words = d.split(",");
int sum = words.length;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == '/' || s.charAt(i) == '*') {
count++;
}
}
if (s.contains(" ")) return false;
return (count <= sum - 1);
}
Thoughts:
I find this question very complex, and I don't know how to arrange the code, because it doesn't seem that my way is correct and and it is so messy. I will be glad for some help. I put a lot of effort into writing this post. Thank you!
Try this.
static final Pattern DIGIT_OR_X = Pattern.compile("[\\dx]");
static final Pattern OPERATION = Pattern.compile("\\([\\dx][+*/%-][\\dx]\\)");
public static boolean isFormula(String s) {
while (true) {
if (DIGIT_OR_X.matcher(s).matches())
return true;
String rep = OPERATION.matcher(s).replaceAll("x");
if (rep.equals(s))
return false;
s = rep;
}
}
Test cases:
assertTrue(isFormula("((6+x)*(4+2))"));
assertTrue(isFormula("(((9*4)+(x+8))*(6-5))"));
assertTrue(isFormula("6"));
assertTrue(isFormula("(3+1)"));
assertFalse(isFormula("-6"));
assertFalse(isFormula("(1+*(x+2)*(1-6))"));
assertFalse(isFormula("( (6+x))"));
assertFalse(isFormula("10"));
assertFalse(isFormula("2+x"));
assertFalse(isFormula("(33+3)"));
assertFalse(isFormula("((1+2))"));
Or you can also do it without regular expression.
static boolean isFormula(String s) {
return new Object() {
int index = 0;
boolean match(String expects) {
if (index >= s.length() || expects.indexOf(s.charAt(index)) < 0)
return false;
++index;
return true;
}
boolean formula() {
if (match("0123456789x"))
return true;
return match("(")
&& formula() && match("+-*/%") && formula()
&& match(")");
}
boolean parse() {
return formula() && index >= s.length();
}
}.parse();
}
I have been trying to figure out how to detect where and what error occurred in a regular infix expression. The first thing that I came up with looks like this...
String expression = "(12 * 12) + (12 * 9)";
int numOfDigits = 0;
int numOfOperators = 0;
boolean onDigit = false;
for (int i = 0; i < expression.length(); i++) {
char ch = expression.charAt(i);
if (Character.isDigit(ch) && !onDigit) {
numOfDigits += 1;
onDigit = true;
} else if (ch == '+' || ch == '-' || ch == '/' || ch == '*') {
numOfOperators += 1;
onDigit = false;
} else if (Character.isWhitespace(ch)) {
onDigit = false;
}
}
if (numOfDigits - 1 != numOfOperators) {
System.out.println("Missing operand(s) or operator(s) in expression");
}
The only issue with this is that I can't detect where in the expression the error is coming from. At this point, I decided to go with something that looks like this as it can detect where in the string the error is coming from. The only problem that I am having with it is that if there is an operator at the end of the string I can't figure out how to allow the program to detect that and display an error. Any help would be greatly appreciated.
for (int i = 0; i < expression.length(); i++) {
char ch = expression.charAt(i);
if (lastType.equalsIgnoreCase("") && (ch == '+' || ch == '-' || ch == '/' || ch == '*')) {
System.out.printf("Missing operand at: %d\n", lastLocation + 1);
break;
}
if (Character.isDigit(ch)) {
if (!onDigit) {
if (lastType.equalsIgnoreCase("digit")) {
System.out.printf("Missing operator at: %d\n", lastLocation + lenOfDigit);
break;
}
lastType = "Digit";
lastLocation = i + 1;
numOfDigits += 1;
onDigit = true;
}
lenOfDigit++;
} else if (ch == '+' || ch == '-' || ch == '/' || ch == '*') {
if (lastType.equalsIgnoreCase("operator")) {
System.out.printf("Missing operand at: %d\n", lastLocation + 1);
break;
}
lastType = "Operator";
lastLocation = i + 1;
numOfOperators += 1;
onDigit = false;
lenOfDigit = 0;
} else if (Character.isWhitespace(ch)) {
onDigit = false;
}
}
You can traverse the string backwards and find the first index where Character.isDigit() is true. Then simultaneously find the first index where the character is an operator. If the index for the operator is larger than the index for the digit, then you've found the discrepancy where an operator is the last character in the expression.
EDIT:
I'm assuming you want to detect when an expression has an operator that is not followed by any digit.
Eg: "(12 * 12) + (12 * 9) +"
You could detect this with:
int lastDigitIndex = -1;
int lastOperatorIndex = -1;
for (int i = expression.length()-1; i >= 0; --i)
{
char ch = expression.charAt(i);
if (Character.isDigit(ch) && lastDigitIndex == -1)
lastDigitIndex = i;
else if((ch == '+' || ch == '-' || ch == '/' || ch == '*') && lastOperatorIndex == -1)
lastOperatorIndex = i;
if (lastDigitIndex != -1 && lastOperatorIndex != -1)
break;
}
if (lastOperatorIndex > lastDigitIndex)
{
//Error found
}
I'm writing a program for class, that as the title says, evaluates infix expressions of unsigned integers using two stacks. The division should be integer division which is why the numbers are integers and not Double. I have created a GUI that gets input from the user and should return the answer. I have attached an ActionListener to the button to compute using this code:
result = Evaluate.evalExp(txtExp.getText());
txtResult.setText(result + "");
The problem is that when I run the program I don't get the correct answer.
For 3-4 I'll get 3, for 6/2 I get 2, and for anything that has parenthesis I get 0 for the answer. I have been trying to figure this out for the better part of the day without any results. I'm hoping someone here will be able to help.
import java.util.Stack;
public class Evaluate {
public static int evalExp(String input) {
char[] tokens = input.toCharArray();
Stack<Integer> number = new Stack<Integer>();
Stack<Character> operator = new Stack<Character>();
int holder = 0;
int ans;
for (int i=0; i < tokens.length; i++) {
// checking to see if token is a number
if (tokens[i] >= '0' && tokens[i] <= '9') {
StringBuffer num = new StringBuffer();
// need to check if number is more than one digit long
while ( i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
num.append(tokens[i++]);
number.push(Integer.parseInt(num.toString()));
}
else if (tokens[i] == '(')
operator.push(tokens[i]);
else if (tokens[i] == ')') {
while (operator.peek() != '(') {
holder = applyOp(operator.pop(), number.pop(), number.pop());
number.push(holder);
}
operator.pop();
}
else if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/') {
// check for precedence
while (!operator.empty() && hasPrecedence(tokens[i], operator.peek())) {
holder = applyOp(operator.pop(), number.pop(), number.pop());
number.push(holder);
}
operator.push(tokens[i]);
}
} // end for loop
while (!operator.empty()) {
holder = applyOp(operator.pop(), number.pop(), number.pop());
number.push(holder);
}
ans = number.pop();
return ans;
} // end of evalExp
// checks to see which operand has a higher precedence if any
public static boolean hasPrecedence(char op1, char op2) {
if (op2 == '(' || op2 == ')')
return false;
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
return false;
else
return true;
} // end hasPrecedence
// return result of operator and operands
public static int applyOp(char op, int b, int a) {
int ans = 0;
switch (op) {
case '+': ans = (a + b);
// return ans;
break;
case '-': ans = (a - b);
// return ans;
break;
case '*': ans = (a * b);
// return ans;
break;
case '/': ans = (a / b);
if (b == 0)
throw new ArithmeticException("Cannot divide by zero");
// return ans;
break;
}
return ans;
} //end applyOp
} //end Class Evaluate
Debugging the same would have given you the answer.
while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
{
num.append(tokens[i++]);
}
In this code when you do i++, you have incremented the value of i but did not handle the char over there which is an operator in your use case.
while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
{
num.append(tokens[i++]);
}
if (i != tokens.length)
i--;
Reverting the increment of the index fixes this issue. This may not be right solution. Just wanted to show the impact of the incremented index.
I am trying to convert string into integers but when I try to print the result I cannnot get the right output.
package com.company;
public class Main {
public static void main(String[] args){
String str ="-123456";
int i = atoi(str);
System.out.println(i);
}
public static int atoi(String str){
if (str == null || str.length() < 1)
return 0;
str = str.trim();
char flag = '+';
int i = 0;
if (str.charAt(0) == '-'){
flag = '-';
i++;
} else if (str.charAt(0) == '+'){
i++;
}
double result = 0;
while (str.length() > 1 && str.charAt(i) >= '0' && str.charAt(i) <= '9'){
result = result * 10 + (str.charAt(i)-'0');
i++;
}
if (flag == '-'){
result = -result;
}
if (result > Integer.MAX_VALUE){
return Integer.MAX_VALUE;
}
if (result < Integer.MIN_VALUE){
return Integer.MIN_VALUE;
}
return (int) result;
}
}
This is the result after I run the code
Change to this: Note i < str.length() instead of str.length() > 1
Explanation: Your error was "index out of range" meaning you're trying to access a character that isn't in the range of the length of the straight and ins this case str.charAt(7), which doesn't exist, so you have to limit i to being less than length of the string.
while (i < str.length() && str.charAt(i) >= '0' && str.charAt(i) <= '9'){
result = result * 10 + (str.charAt(i)-'0');
i++;
}
I want to check if every character in a string is the inverse of the other character in the second. By inverse I mean uppercase and lowercase.
For example these strings:
Ahh7h
aHH7H
The result will be true
I wrote this code but the result is always false. Why?
public boolean checkString(String serverString, String clientString) {
if (serverString.length() != clientString.length())
return false;
else
for (int i = 0; i < clientString.length(); i++) {
if ((clientString.charAt(i) >= '0' && clientString.charAt(i) <= '9')
&& (clientString.charAt(i) != serverString.charAt(i)))
return false;
else if (clientString.charAt(i) >= 'A'
&& clientString.charAt(i) <= 'Z') {
if ((int) clientString.charAt(i) != ((int) serverString
.charAt(i) + 32))
return false;
} else if (clientString.charAt(i) >= 'a'
&& clientString.charAt(i) <= 'z') {
if ((int) clientString.charAt(i) != ((int) serverString
.charAt(i) - 32))
return false;
}
}
return true;
}
You could "invert" one string using: How can I invert the case of a String in Java? and then use Strings .equals method to compare them.
Method from How can I invert the case of a String in Java? included for completeness:
public static String reverseCase(String text)
{
char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++)
{
char c = chars[i];
if (Character.isUpperCase(c))
{
chars[i] = Character.toLowerCase(c);
}
else if (Character.isLowerCase(c))
{
chars[i] = Character.toUpperCase(c);
}
}
return new String(chars);
}
You've switched the + 32 and the - 32.
By the way, it's a lot easier to use methods like:
Character.isDigit
Character.isLowerCase
Character.isUpperCase
Character.toLowerCase
Character.toUpperCase