Suiter21 Suiter21 - 1 month ago 9
Java Question

How can I split sin, cos, and tan from my String and insert it into an ArrayList index using regular expressions? (Java)

I am trying to build a calculator by converting infix to postfix but I've been having trouble with handling cos, sin, and tan. My current approach is to use regular expressions to split the input string by the cos, sin, etc and numbers then placing them into indexes of an ArrayList. I have been able to get cos0 to split into two ArrayList indexes, but the index that's supposed to hold cos turns up empty. I don't know if I am using regular expressions wrong or if it's something else.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;



public class Calculator {

//String sin = "sin";
//String cos = "cos";
//String tan = "tan";

public static void main(String[] args) {
new Calculator().run();
}

public void run() {
Calculator Eval = new Calculator();
Scanner keyboard = new Scanner(System.in);
System.out.println("Please give an equation.");

String input = keyboard.next();

System.out.print(Eval.infixToPostfix(input));
}

public double infixToPostfix(String input)
{

Stack<String>infixStack = new Stack<>();
ArrayList<String> exp = new ArrayList<>(Arrays.asList(input.split("(cos|tan|sin\\d\\D)")));

String infix = "";

for (int i = 0; i < exp.size(); i++)
{
if(exp.get(i).equals("")){
continue;
}
if (exp.get(i).matches("([\\d])")) {

infix = infix + exp.get(i);

}else if(exp.get(i).matches("([\\D])"))
{
while(!infixStack.empty() && !infixStack.peek().matches("[\\(\\[\\{\\^]") && OperatorPriority(infixStack.peek(), exp.get(i) ))
{
infix = infix + infixStack.peek();
infixStack.pop();
}
infixStack.push(exp.get(i));
}else if(exp.get(i).matches("[(]"))
{
infixStack.push(exp.get(i));
}else if(exp.get(i).matches("[)]"))
{
while(!infixStack.empty() && !infixStack.peek().matches("[(]"));
{
infix = infix + infixStack.peek();
infixStack.pop();
}
infixStack.pop();
}else if(exp.get(i).matches("[\\^]"))
{
infixStack.push(exp.get(i));
}else if(exp.get(i).matches("[\\[]"))
{
infixStack.push(exp.get(i));
}else if(exp.get(i).matches("[\\]]"))
{
while(!infixStack.empty() && !infixStack.peek().matches("[\\(\\[]"))
{
infix = infix + infixStack.peek();
infixStack.pop();
}

infixStack.pop();
} else if(exp.get(i).matches("[\\{]"))
{
infixStack.push(exp.get(i));
}else if(exp.get(i).matches("[\\}]"))
{
while(!infixStack.empty() && !infixStack.peek().matches("[\\(\\{\\[]"))
{
infix = infix + infixStack.peek();
infixStack.pop();
}
infixStack.pop();
}
}

while(!infixStack.empty())
{
infix = infix + infixStack.peek();
infixStack.pop();
}
return evaluatePostFix(infix);
}

public double evaluatePostFix(String infix) {
Stack<Double> equation = new Stack<Double>();
ArrayList<String> postfixArray = new ArrayList<>(Arrays.asList(infix.split("(?<=[\\w'(cos|tan|sin)'\\d])|(?=[\\w'(cos|tan|sin)'\\d])")));


double first;
double second;

try {
for (int i = 0; i < postfixArray.size(); i++) {
if (postfixArray.get(i).matches("([\\d])")) {
double d = Double.parseDouble(postfixArray.get(i));
equation.push(d - '0');
}else if(postfixArray.get(i).matches("([sin])"))
{
first = equation.pop();
//second = equation.pop();
double result = Math.sin(Math.toRadians(first));
equation.push(result);
}else if(postfixArray.get(i).matches("([cos])"))
{
first = equation.pop();
//second = equation.pop();
double result = Math.cos(Math.toRadians(first));
equation.push(result);
}else if(postfixArray.get(i).matches("([tan])"))
{
first = equation.pop();
//second = equation.pop();
double result = Math.tan(Math.toRadians(first));
equation.push(result);
}

if (postfixArray.get(i).matches("[*]")) {
first = equation.pop();
second = equation.pop();
double result = first * second;
equation.push(result);
}

if (postfixArray.get(i).matches("[/]")) {
first = equation.pop();
second = equation.pop();
double result = second / first;
equation.push(result);
}

if (postfixArray.get(i).matches("[+]")) {
first = equation.pop();
second = equation.pop();
double result = first + second;
equation.push(result);
}

if (postfixArray.get(i).matches("[-]")) {
first = equation.pop();
second = equation.pop();
double result = first - second;
equation.push(result);
}

if (postfixArray.get(i).matches("[(^)]")) {
first = equation.pop();
second = equation.pop();
double result = Math.pow(first, second);
equation.push(result);
}
}

if (!equation.isEmpty()) {
return equation.pop();
} else
return 0.0;
} catch (Exception e ) {
return 0.0;
}
}

int OperatorWeight(String op)
{
int weight = 1;
if(op.equals("+") || op.equals("-"))
{
weight = 1;
}else if(op.equals("*") || op.equals("/") )
{
weight = 2;
}else if(op.equals("^"))
{
weight = 3;
}
return weight;
}

boolean OperatorPriority(String operator1, String operator2)
{
int weight1 = OperatorWeight(operator1);
int weight2 = OperatorWeight(operator2);

if(weight1 == weight2)
{
return true;
}
return weight1 > weight2;
}
}

Answer

Assuming the following input format:

valid - cos49

invalid - cos43.54

invalid - sin(angle)

You can divide your string into two groups:

  1. sin|cos|tan
  2. digits

So your regex should look like this:

Pattern p = Pattern.compile("(sin|cos|tan)|(\\d+)");
Matcher m = p.matcher("cos60");
ArrayList<String> a = new ArrayList<>();
while (m.find())
    a.add(m.group(0));

System.out.println(a.toString());

Read how the matcher class works. Hope it helps