Write a program for finding duplicate parenthesis in a expression.
For example :
(( a + b ) + (( c + d ))) = a + b + c + d
(( a + b ) * (( c + d ))) = (a + b) * (c + d)
One approach that I am aware of involves the following two steps:
Convert the given infix expression to postfix expression.
Convert back the postfix to infix
I don't want to do this entire process of converting from one representation to another, and then convert it back.
I want to do this using stack(s) but in a single pass. Is it possible ?
Please suggest an algorithm or share the code.
You can use a recursive descent parser. This uses the function call stack implicitly, but not explicitly a Java stack. It can be implemented as follows:
public class Main {
public static void main(String[] args) {
System.out.println(new Parser("(( a + b ) + (( c + d )))").parse());
System.out.println(new Parser("(( a + b ) * (( c + d )))").parse());
}
}
public class Parser {
private final static char EOF = ';';
private String input;
private int currPos;
public Parser(String input) {
this.input = input + EOF; // mark the end
this.currPos = -1;
}
public String parse() throws IllegalArgumentException {
nextToken();
Result result = expression();
if(currToken() != EOF) {
throw new IllegalArgumentException("Found unexpected character '" + currToken() + "' at position " + currPos);
}
return result.getText();
}
// "expression()" handles "term" or "term + term" or "term - term"
private Result expression() throws IllegalArgumentException {
Result leftArg = term();
char operator = currToken();
if (operator != '+' && operator != '-') {
return leftArg; // EXIT
}
nextToken();
Result rightArg = term();
if(operator == '-' && (rightArg.getOp() == '-' || rightArg.getOp() == '+')) {
rightArg = encloseInParentheses(rightArg);
}
return new Result(leftArg.getText() + " " + operator + " " + rightArg.getText(), operator);
}
// "term()" handles "factor" or "factor * factor" or "factor / factor"
private Result term() throws IllegalArgumentException {
Result leftArg = factor();
char operator = currToken();
if (operator != '*' && operator != '/') {
return leftArg; // EXIT
}
nextToken();
Result rightArg = factor();
if(leftArg.getOp() == '+' || leftArg.getOp() == '-') {
leftArg = encloseInParentheses(leftArg);
}
if(rightArg.getOp() == '+' || rightArg.getOp() == '-' || (operator == '/' && (rightArg.getOp() == '/' || rightArg.getOp() == '*'))) {
rightArg = encloseInParentheses(rightArg);
}
return new Result(leftArg.getText() + " " + operator + " " + rightArg.getText(), operator);
}
// "factor()" handles a "paren" or a "variable"
private Result factor() throws IllegalArgumentException {
Result result;
if(currToken() == '(') {
result = paren();
} else if(Character.isLetter(currToken())) {
result = variable();
} else {
throw new IllegalArgumentException("Expected variable or '(', found '" + currToken() + "' at position " + currPos);
}
return result;
}
// "paren()" handles an "expression" enclosed in parentheses
// Called with currToken an opening parenthesis
private Result paren() throws IllegalArgumentException {
nextToken();
Result result = expression();
if(currToken() != ')') {
throw new IllegalArgumentException("Expected ')', found '" + currToken() + "' at position " + currPos);
}
nextToken();
return result;
}
// "variable()" handles a variable
// Called with currToken a variable
private Result variable() throws IllegalArgumentException {
Result result = new Result(Character.toString(currToken()), ' ');
nextToken();
return result;
}
private char currToken() {
return input.charAt(currPos);
}
private void nextToken() {
if(currPos >= input.length() - 1) {
throw new IllegalArgumentException("Unexpected end of input");
}
do {
++currPos;
}
while(currToken() != EOF && currToken() == ' ');
}
private static Result encloseInParentheses(Result result) {
return new Result("(" + result.getText() + ")", result.getOp());
}
private static class Result {
private final String text;
private final char op;
private Result(String text, char op) {
this.text = text;
this.op = op;
}
public String getText() {
return text;
}
public char getOp() {
return op;
}
}
}
If you want to use an explicit stack, you could convert the algorithm from a recursive one to an iterative one, using a stack of something similar to the Result inner class.
In fact, the Java compiler/JVM converts each recursive algorithm to a stack based one putting the local variables onto a stack.
But recursive decent parsers are easily readable by humans, hence I would prefer the solution presented above.
If you only care about duplicate parentheses (as the question seems to imply), rather than those deemed necessary due to operator precedence (as the other answers seem to imply) you can indeed use a stack to keep track of which brackets you have encountered, and decide that any non-whitespace non-bracket characters for each pair of parentheses matters, which gives you a much simpler iterative traversal using a stack:
public class BracketFinder {
public List<BracketPair> findUnnecessaryBrackets(String input) {
List<BracketPair> unneccessaryBrackets = new LinkedList<BracketPair>();
Deque<BracketPair> bracketStack = new LinkedBlockingDeque<BracketPair>();
for (int cursor = 0; cursor < input.length(); cursor++ ) {
if (input.charAt(cursor) == '(') {
BracketPair pair = new BracketPair(cursor);
bracketStack.addLast(pair);
} else if (input.charAt(cursor) == ')') {
BracketPair lastBracketPair = bracketStack.removeLast();
lastBracketPair.end = cursor;
if (!lastBracketPair.isNecessary) {
unneccessaryBrackets.add(lastBracketPair);
}
} else if (input.charAt(cursor) != ' ') {
if (!bracketStack.isEmpty()) {
bracketStack.getLast().isNecessary = true;
}
}
}
return unneccessaryBrackets;
}
class BracketPair {
public int start = -1;
public int end = -1;
public boolean isNecessary = false;
public BracketPair(int startIndex) {
this.start = startIndex;
}
}
}
Which you can test with the following
public static void main(String... args) {
List<BracketPair> results = new BracketFinder().findUnnecessaryBrackets("(( a + b ) + (( c + d ))) = a + b + c + d");
for (BracketPair result : results) {
System.out.println("Unneccessary brackets at indices " + result.start + "," + result.end);
}
}
Did not program it, but it could be look like this:
give the operations + / - the value 1
give the operations * & / the value 2
give the operation )( the value 2 (as its the same like *)
1 go to inner parenthesis and check if the next operation is higher in its value (means the parenthesis is necessary) or equal/lower to the own operation. if equal or lower the parenthesis is not necessary.
2 go to 1
you are finished, when there are no changes between 2 steps
hope this helped..
If you got an solution let me know please.
If this didn't help, let me know too :)
Greetings
Its possible in one pass. The idea is to look for previous / next operation around each () block and apply associativity rules. Here is small table with yes/no marks when () is necessary.
// (a + b) + c NO
// (a + b) - c NO
// (a + b) / c YES
// (a + b) * c YES
// (a / b) + c NO
// (a / b) - c NO
// (a / b) / c NO
// (a / b) * c NO
// a + (b + c) NO
// a - (b + c) YES
// a / (b + c) YES
// a * (b + c) YES
// a + (b / c) NO
// a - (b / c) NO
// a / (b / c) YES
// a * (b / c) NO
// (a) ((a)) NO
Here is C++ code (im not sure if its not missing some cases - its just an idea):
string clear(string expression)
{
std::stack<int> openers;
std::stack<int> closers;
std::stack<bool> isJustClosed;
std::stack<char> prevOperations;
std::stack<bool> isComposite;
std::stack<int> toDelete;
prevOperations.push(' ');
isJustClosed.push(false);
isComposite.push(false);
string result = expression + "#";
for (int i = 0; i < result.length(); i++)
{
char ch = result[i];
if ((ch == '*') || (ch == '/') || (ch == '+') || (ch == '-') || (ch == '(') || (ch == ')') || (ch == '#'))
if (isJustClosed.size() > 0)
if (isJustClosed.top() == true) {
// pop all and decide!
int opener = openers.top(); openers.pop();
int closer = closers.top(); closers.pop();
char prev = prevOperations.top(); prevOperations.pop();
char prevOperationBefore = prevOperations.top();
isJustClosed.pop(); //isJustClosed.push(false);
bool isComp = isComposite.top(); isComposite.pop();
bool ok = true;
if (prev == ' ')
ok = false;
else
{
ok = false;
if (((isComp) || (prev == '+') || (prev == '-')) && (ch == '/')) ok = true;
if (((isComp) || (prev == '+') || (prev == '-')) && (ch == '*')) ok = true;
if (((isComp) || (prev == '+') || (prev == '-')) && (prevOperationBefore == '-')) ok = true;
if (prevOperationBefore == '/') ok = true;
if (((isComp) || (prev == '+') || (prev == '-')) && (prevOperationBefore == '*')) ok = true;
}
if (!ok)
{
toDelete.push(opener);
toDelete.push(closer);
}
}
if (ch == '(') {
openers.push(i);
prevOperations.push(' ');
isJustClosed.push(false);
isComposite.push(false);
}
if (ch == ')') {
closers.push(i);
isJustClosed.top() = true;
}
if ((ch == '*') || (ch == '/') || (ch == '+') || (ch == '-')) {
if (!isComposite.top())
{
char prev = prevOperations.top();
if ((ch == '+') || (ch == '-'))
if ((prev == '*') || (prev == '/'))
isComposite.top() = true;
if ((ch == '*') || (ch == '/'))
if ((prev == '+') || (prev == '-'))
isComposite.top() = true;
}
prevOperations.top() = ch;
isJustClosed.top() = false;
}
}
while (toDelete.size() > 0)
{
int pos = toDelete.top();
toDelete.pop();
result[pos] = ' ';
}
result.erase(result.size() - 1, 1);
return result;
}
Inside each block we track last operation and also track if content is composite like (a+b*c).
Test:
void test()
{
LOG << clear("((a + (a + b))) - ((c)*(c) + d) * (b + d)") << NL;
LOG << clear("a + (a + b) - ((c) + d) * (b + d)") << NL;
LOG << clear("(a/b)*(c/d)") << NL;
LOG << clear("(a/b)*((((c)/d)))") << NL;
LOG << clear("((a + b) - (c - d))") << NL;
LOG << clear("((a + b)*((c - d)))+c/d*((a*b))") << NL;
LOG << clear("a+a*b*(a/b)") << NL;
LOG << clear("a+a*b*(a+b)") << NL;
}
Result:
a + a + b - ( c * c + d) * b + d
a + a + b - ( c + d) * b + d
a/b * c/d
a/b * c /d
a + b - (c - d)
(a + b)* c - d +c/d* a*b
a+a*b* a/b
a+a*b*(a+b)
Personally I think there are at least 2 ways:
using a tree
using arithmetical polish notation
Tree
A tree can be created from the input expression. After the tree is created it can be flattened without the useless parentheses
Binary_expression_tree
parsing-an-arithmetic-expression-and-building-a-tree
Polish notation
(( a + b ) + (( c + d ))) will become (+ (+ a b) (+ c d))
(( a + b ) * (( c + d ))) will become (* (+ a b) (+ c d))
From here you could compare the each operand and the factors to see if they have the same priority in solving the arithmetical equation
I would go with the tree.
Related
I've found some problem with Matcher.replaceFirst/replaceAll when subgroup count in regex is more than 9...
simple example:
String res = "abcdefghij".replaceFirst("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)", "$1 $2 $3 $4 $5 $6 $7 $8 $9 $10");
Expected result is "a b c d e f g h i j" but got "a b c d e f g h i a0" string.
This problem can reproduced in Android runtime, but on local unit tests with desktop java it works well.
When I tried to debug it step by step, I've found following ugly code in Android sources of Matcher class:
private void appendEvaluated(StringBuffer buffer, String s) {
boolean escape = false;
boolean dollar = false;
boolean escapeNamedGroup = false;
int escapeNamedGroupStart = -1;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\' && !escape) {
escape = true;
} else if (c == '$' && !escape) {
dollar = true;
} else if (c >= '0' && c <= '9' && dollar) { //<<<<------ WHAT IS IT?!
buffer.append(group(c - '0'));
dollar = false;
} else if (c == '{' && dollar) {
escapeNamedGroup = true;
escapeNamedGroupStart = i;
} else if (c == '}' && dollar && escapeNamedGroup) {
String namedGroupName =
s.substring(escapeNamedGroupStart + 1, i);
buffer.append(group(namedGroupName));
dollar = false;
escapeNamedGroup = false;
} else if (c != '}' && dollar && escapeNamedGroup) {
continue;
} else {
buffer.append(c);
dollar = false;
escape = false;
escapeNamedGroup = false;
}
}
if (escape) {
throw new IllegalArgumentException("character to be escaped is missing");
}
if (dollar) {
throw new IllegalArgumentException("Illegal group reference: group index is missing");
}
if (escapeNamedGroup) {
throw new IllegalArgumentException("Missing ending brace '}' from replacement string");
}
}
this is part of SDK API 29... I've checked API 30 level, it has same code.
maybe someone already solve this problem?
I think it needs to create custom replacer with more correct logic...
My program works fine, but I'm getting some irregular spaces in the output. For example, if the input is 44 * 5 + 6 the output is 44<2 spaces>5<1 space>*<1space>6<no space>+. I tried fiddling with all the lines of code that are adding to the String postfix, but to no avail. I'd like the output to be of the form: operand<1 space>operand<1 space>operator (i.e. 1 space between operands and operators."
Here's my code:
import java.util.*;
public class PostfixConversion {
public static void main(String args[]) {
System.out.print("Enter an expression: ");
String infix = new Scanner(System.in).nextLine();
String postfix = convertToPostfix(infix);
System.out.println(postfix);
//System.out.println("The result of calculation is: " + postfixEvaluate("23+"));
}
//converts infix expression into postfix expression
public static String convertToPostfix(String infixExp) {
String postFix = "The Postfix Expression is: ";
Stack<Character> stack = new Stack<Character>();
char character = ' ';
for(int i = 0; i < infixExp.length(); i++)
{
character = infixExp.charAt(i);
//determine if character is an operator
if(character == '*' || character == '-' || character == '/' || character == '+')
{
//postFix += " ";
while(!stack.empty() && precedence(stack.peek(), character))
postFix += stack.pop();
stack.push(character);
} else if(character == '(') {
stack.push(character);
} else if(character == ')') {
while(!stack.peek().equals('(') && !stack.isEmpty())
postFix += stack.pop();
if(!stack.isEmpty() && stack.peek().equals('('))
stack.pop(); // pop/remove left parenthesis
} else
postFix += character;
}
while(!stack.empty()) //add the remaining elements of stack to postfix expression
{
if(stack.peek().equals('('))
{
postFix = "There is no matching right parenthesis.";
return postFix;
}
postFix += stack.pop();
}
return postFix;
}
public static boolean precedence(char first, char second) {
int v1 = 0, v2 = 0;
//find value for first operator
if(first == '-' || first == '+')
v1 = 1;
else if(first == '*' || first == '/')
v1 = 2;
//find value for second operator
if(second == '-' || second == '+')
v2 = 1;
else if(second == '*' || second == '/')
v2 = 2;
if(v1 < v2)
return false;
return true;
}
First remove all whitespaces from input, so that they don't destroy your formatting:infixExp = infixExp.replaceAll("\\s",""); and then add whitespaces where needed.
I'm trying to convert a postfix into an infix. I have some code, but I'm not able to fix it. There may be a condition I am missing. Or my structure is not quite right.
Also since I am new to Java I may need some help with "Stack<Character>".
public static String postfixToInfix(String postfix) {
Stack<Character> stack = new Stack();
Stack<Character> backup = new Stack();
StringBuilder infix = new StringBuilder(postfix.length());
infix.append('(');
for (int i = 0; i < postfix.length(); i++) {
if (!isOperator(postfix.charAt(i))) {
stack.push(postfix.charAt(i));
} else {
if (stack.size() == 1 ) { //stack is 1
backup.push(postfix.charAt(i));
}
if (stack.size() == 0 && backup.size()%5 == 0) { //stack is 0
stack.push(backup.pop());
stack.push(backup.pop());
stack.push(backup.pop());
stack.push(backup.pop());
stack.push(backup.pop());
stack.push(postfix.charAt(i));
}
if (stack.size() >= 2) { //stack is > 1
char arg2 = stack.pop();
char arg1 = stack.pop();
backup.push(')');
backup.push(arg2);
backup.push(postfix.charAt(i));
backup.push(arg1);
backup.push('(');
}
}
}
while (!backup.empty()) { //only size 3
stack.push(backup.pop());
}
while (!stack.empty()) { //only size 3
backup.push(stack.pop());
}
while (!backup.isEmpty()) {
infix.append(backup.pop());
}
infix.append(')');
return infix.toString();
}
private static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '(' || c == ')';
}
public static void main(String[] args) {
String infix1 = "(3-(7*2))";
String postfix1 = "372*-";
String infix2 = "((7+1)*((3-6)*(5-2)))";
String postfix2 = "71+36-52-**";
System.out.println(" postfix1: " + postfix1);
s = postfixToInfix(postfix1);
System.out.println("postfixToInfix(postfix1): " + s);
if (s.equals(infix1)) {
System.out.println(" Korrekt!");
} else {
System.out.println(" Nicht korrekt!");
}
System.out.println();
System.out.println(" postfix2: " + postfix2);
s = postfixToInfix(postfix2);
System.out.println("postfixToInfix(postfix2): " + s);
if (s.equals(infix2)) {
System.out.println(" Korrekt!");
} else {
System.out.println(" Nicht korrekt!");
}
System.out.println();
}
}
Output
postfix1: 372*-
postfixToInfix(postfix1): (3-(7*2))
Korrekt!
postfix2: 71+36-52-**
postfixToInfix(postfix2): ((5(-*2)()**)(3-6)(7+1))
Nicht korrekt!
Process finished with exit code 0
Instead of dealing with the parenthesis and everything as separate entries in the stack, you could use strings to simplify the process:
private static boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}
public static String postfixToInfix(String postfix) {
Stack<String> s = new Stack<String>();
for (char c : postfix.toCharArray()) {
if (isOperator(c)) {
String temp = s.pop();
s.push('(' + s.pop() + c + temp + ')');
} else {
s.push(String.valueOf(c));
}
}
return s.pop();
}
I want to use properties files through PropertyResourceBundle for i18n. My current issue is that keys on the files I have can include white spaces, e.g. :
key number 1 = value number 1
key2 = value2
So, when I load the corresponding property file the first white space is used as the key-value delimiter instead of the '=' sign.
Then, my questions are: how can I use a key with white spaces in it without modifying the properties file (I'd like to avoid adding any slash or unicode character code)? Is there any way to override the default properties file delimiter so I can set '=' as the only one to be considered?
you will have to write your own Properties class, the one in the jdk considers white space as a separator, here is it's code. you'll find out that as soon as it encounter a white space it stop the key & start the value.
private void load0 (LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
int limit;
int keyLen;
int valueStart;
char c;
boolean hasSep;
boolean precedingBackslash;
while ((limit = lr.readLine()) >= 0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
//System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
precedingBackslash = false;
while (keyLen < limit) {
c = lr.lineBuf[keyLen];
//need check if escaped.
if ((c == '=' || c == ':') && !precedingBackslash) {
valueStart = keyLen + 1;
hasSep = true;
break;
} else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
valueStart = keyLen + 1;
break;
}
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
keyLen++;
}
while (valueStart < limit) {
c = lr.lineBuf[valueStart];
if (c != ' ' && c != '\t' && c != '\f') {
if (!hasSep && (c == '=' || c == ':')) {
hasSep = true;
} else {
break;
}
}
valueStart++;
}
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
}
I'm attempting to write an infix to postfix calculator. I am reading from a file that contains:
(4>3)+(3=4)+2
When i run my code, i should be getting a string containing the postfix notation of the input,
however i get absolutely nothing. my code doesnt seem to be reaching the final print statement. also when i modidy the code to get it to at least print(although the notation is incorrect) it only prints the numbers and not the operators ( +, -, &, etc). I cannot figure out why this is happening! i labeled in the code below where the print statement is:
public static void main(String[] args) {
readMathFile();
}
static String PF = "";
public static void postfix(char c, myStack s, myQueue q) {
if (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' ||
c == '5' || c == '6' || c == '7' || c == '8' || c == '9') {
String cc = Character.toString(c);
PF.concat(cc);
} else if(c == '!' || c == '*' || c == '/' || c == '+' || c == '-' ||
c == '<' || c == '>' || c == '=' || c == '&' || c == '|') {
if(s.isEmpty())
s.push(c);
else {
char top = s.peek();
while ((precedence(top) > precedence(c)) && !s.isEmpty()) {
String cd = Character.toString(s.pop());
PF.concat(cd);
}
s.push(c);
}
}
}
public static myStack s;
public static myQueue q;
public static int i = 1;
// the file reading code was borrowed from:
// http://www.java2s.com/Code/Java/File-Input-Output/Readfilecharacterbycharacter.htm
public static void readMathFile() {
s = new myStack();
q = new myQueue();
File file = new File("test.txt");
if (!file.exists()) {
System.out.println(file + " does not exist.");
return;
}
if (!(file.isFile() && file.canRead())) {
System.out.println(file.getName() + " cannot be read from.");
return;
}
try {
FileInputStream fis = new FileInputStream(file);
char current;
// in this while loop is where all of the reading happens
while (fis.available() > 0) {
current = (char) fis.read();
//readMath(current, s, q);
postfix(current, s, q);
}
if(fis.available() == 0) {
char x = s.pop();
while(!s.isEmpty()) {
//q.enqueue(s.pop());
String ce = Character.toString(s.pop());
PF.concat(ce);
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("\n\n"+PF); // <----CODE NEVER REACHES THIS POINT! (and when i modify so it does, it will not print the operators!)
}