Friday, April 8, 2016

Java Regular Expressions with small example

Problem: 
We will get the string with some format which we need to resolve into Airthemetic operations and give final result:
format for the input string:
 (operator val1 val2 (operator val3 val4 val5)  (operator val6  (operator val7 val8)))
like this
below is one example:
(+ 3 4 5) = 3+ 4+ 5 = 12
(* 2 (+ 1 3) )= 2 * (1+3) = 2*4 = 8

Solution:
I chose to solve this using Java regular expression which fits my custom needs and can solve this without relying on some third party solutions and which is also best in performance as i am using Pattern to compile and then using Matcher to find matches which will boost up the performance rather than using Pattern.matches() on the string.

Hope the below functions gives you are glance on how to solve the issue:
public static boolean hasInnerSubquery(String str){
String patternStyle = "(\\(.*(.*\\(.*\\).*).*\\)) ";
Pattern pattern = Pattern.compile(patternStyle);
Matcher matcher = pattern.matcher(str);
while(matcher.find()){
return true;
}
return false;
}

/* this is used to resolve existing inner subqueries
* and replace the inner subquery in the string with
* the computed result and return the final replaced string
*/
public static String resolveInnerSubquery(String str) {
String patternStyle = "(\\(.*(.*\\(.*\\).*).*\\)) "; 
                //in regex grouping is done using (), and if say ([abc])([def]) that means there are
               // two groups one group which checks either a or b or c and other one group alterative
              // similarly the patternstyle i have used above checks for () inside the parenthesis --( ( ) )
             //  and try to solve the code inside the inner parenthesis.
Pattern pattern = Pattern.compile(patternStyle);
Matcher matcher = pattern.matcher(str);
int groupCount = matcher.groupCount();
while(matcher.find()){
System.out.println(matcher.group(groupCount));
String innerSubquery= matcher.group(groupCount);
innerSubquery = innerSubquery.substring(innerSubquery.indexOf('('), innerSubquery.indexOf(')')+1);
double result=calculate(innerSubquery.substring(1,innerSubquery.length()-1));
str= str.replace(innerSubquery,String.valueOf(result));
System.out.println(result);
}
return str;
}
     
     /*
* this is used to compute the final double result from the input string
* the format is like <operator> <val1> <val2> [ <val3> ...]
*/
public static double calculate(String str) {
List<String> params = null;
double result = 0;
String operator = "";
String[] strs1 = str.split("\\s+");
params = Arrays.asList(strs1);
if (params.size() >= 3) {
Iterator<String> iterator = params.iterator();
operator = iterator.next();
result = Double.parseDouble(iterator.next());
while (iterator.hasNext()) {
switch (operator) {
case "+":
result += Double.parseDouble(iterator.next());
break;
case "-":
result -= Double.parseDouble(iterator.next());
break;
case "*":
result *= Double.parseDouble(iterator.next());
break;
case "/":
result /= Double.parseDouble(iterator.next());
break;
case "%":
result %= Double.parseDouble(iterator.next());
break;
}
}
}

return result;
}

public static double performOperation(String str){
double result=0;
String input = str.substring(1,str.lastIndexOf(')'));
while(hasInnerSubquery(input)){
input=resolveInnerSubquery(input);
}
                result = calculate(input);
      }

Try this example out with your own requirements and have fun.