2

I want to replace the "cube root of" and "square root of" in a String to respectively "^(1/3)" and "^(1/2)", but after the operand.

Making a simple replace would put "^(1/3)" and "^(1/2)" ahead of the numbers, but I need them to be after the numbers (I am working with an ExpressionBuilder API from exp4j, which requires this).

For example, given this string:

"cube root of 27 times cube root of 64 plus square root of 9 minus square root of 4"

I want it to be converted to:

"27^(1/3)*64^(1/3)+9^(1/2)-4^(1/2)"

Here's my attempt:

String equation = "cube root of 27 times square root of 45";
String r1 = equation.replaceAll("cube root of", "◊").replaceAll("square root of", "√")
        .replaceAll("times", "*").replaceAll("plus", "+").replaceAll("minus", "-")
        .replaceAll("divided by", "/").replaceAll(" ", "");

System.out.println(r1);
String r2 = null;
if (r1.contains("◊"))
{
    for (int i = r1.indexOf("◊")+1; i < r1.length(); i++)
    {
        if(Character.isDigit(r1.charAt(i)))
        {

        }
        else
        {
            System.out.println("i: " + i);
            r2 = r1.substring(r1.indexOf("◊")+1, i) + "^(1/3)" + r1.substring(i);
            break;
        }
    }
}
System.out.println(r2);

I've replaced a temporary character "◊" for "cube root of" (gets tedious writing the whole phrase out), and I've gotten it to work for me where the output I get is:

◊27*√45
i: 3
27^(1/3)*√45

So it works only for one "cube root of" phrase, not two, and fails to work the "square root of" phrase (It's not in the code, but I tried incorporating this in my code in the first if() block where I see if the String contains the "◊" symbol.

I tried using the OR r1.contains("√") operator in that if() block, but it screwed things up with my existing code. I have looked everywhere online for a solution. I've tried methods such as a replaceCharAt(String s, int position, char c) in my program to replace the character at the specified position, but I couldn't get it to work with all occurrences of the specified phrases.

I've spent weeks on finding a solution, but I can't find one in which I can replace BOTH phrases for a mathematical operation.

I would greatly appreciate any help posted here.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
Cid
  • 66
  • 7
  • for starters, don't use `replaceAll()`, just use `replace()`, which still replaces all occurrences, but does a plain-text replace (not a regex replace) – Bohemian Apr 25 '16 at 19:00
  • so, you want "cube root of 27" to become "27^(1/3)" etc? – Bohemian Apr 25 '16 at 19:07
  • Yes, that is my intent. If the phrase was "cube root of 27 times cube root of 64 times square root of 9 times square root of 4", I would want it to be translated to: "27^(1/3)*64^(1/3)*9^(1/2)*4^(1/2). The * operator could be anything really, like +,-, or even / – Cid Apr 25 '16 at 19:11

2 Answers2

1

Assuming you want to transform "cube root of 123" to "123^(1/3)" etc (your question is unclear), capture the operand and use a back reference:

equation = equation.replaceAll("cube root of (\\S+)", "$1^(1/3)")
                   .replaceAll("square root of (\\S+)", "$1^(1/2)")
                   .replace("times", "*").replace("plus", "+").replace("minus", "-")
                   .replace("divided by", "/").replace(" ", "");

Note that for non-regex replacements, the plain-text replace() is sufficient (and preferred) - it still replaces all occurrences, but without using regex.


Some test code:

String equation = "cube root of 8 times square root of 4 plus cube root of 27 minus 3";
equation = equation.replaceAll("cube root of (\\S+)", "$1^(1/3)")
                   .replaceAll("square root of (\\S+)", "$1^(1/2)")
                   .replace("times", "*").replace("plus", "+").replace("minus", "-")
                   .replace("divided by", "/").replace(" ", "");
System.out.println(equation);

Output:

8^(1/3)*4^(1/2)+27^(1/3)-3
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Such a simple and elegant answer! Thank you so much Bohemian! My intent was to take a string such as: "cube root of 27 minus square root of 4 plus square root of 9 times cube root of 64" for example, and turn it into: "27^(1/3) - 4^(1/2) + 9^(1/2) * 64^(1/3), and this worked awesomely Once again, thank you! – Cid Apr 25 '16 at 19:21
  • @cid np. it would be useful for you to learn regex. fyi `\S` means "non whitespace character", using brackets "captures" the input, `$1` means "group 1" (capturing groups are numbered from 1). – Bohemian Apr 25 '16 at 19:26
0

Hello here is one naive implementation. First you can accumulate all the values matching the regular expression strings that you have. You have the following regular expression.

RegEx of type "cube" or "square" followed by "root of" followed by digit. Now that you have constructed you RegEx you use

    String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(0));
}

This will extract you the values of the digits. Once you do that you need to replace the full occurrence of the regular expression with what you want.

Probably there are better implementations of this. It is the first that came into my mind. Basically you need to play more with the regular expressions before trying to replace anything. And think of it as a whole thing a whole regular expression instead of trying to divide it to smaller elements.

Alexander Petrov
  • 9,204
  • 31
  • 70