views:

1930

answers:

7

As part of a project for school, I need to replace a string from the form:

5 * x^3 - 6 * x^1 + 1

to something like:

5x<sup>3</sup> - 6x<sup>1</sup> + 1

I believe this can be done with regular expressions, but I don't know how to do it yet.

Can you lend me a hand?

P.S. The actual assignment is to implement a Polynomial Processing Java application, and I'm using this to pass polynomial.toString() from the model to the view, and I want do display it using html tags in a pretty way.

+2  A: 
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
Can Berk Güder
ah... but you missed collapsing the "5 * x" to "5x"
James Curran
we leave that as an exercise to the reader =)
Can Berk Güder
Couple problems: \^ needs to be \\^ and $ needs to be \$.
cdmckay
Still getting error "invalid escape sequence" ... am i missing something?
Dan
@Dan: how many backslashes did you use with ^ and $?
Michael Myers
@cdmckay: thanks. I'll edit my answer accordingly.
Can Berk Güder
this gives me an error at the second parameter:str.replaceAll("\\^([0-9]+)", "<sup>\$1</sup>");I don't get it... :(
Dan
You need another backslash before the $.
Michael Myers
No, there shouldn't be any backslashes in the replacement string.
Alan Moore
@Alan M: Heh, you're right. Another backslash would allow it to compile, but it wouldn't do anything useful.
Michael Myers
A: 

You'll want to look into capturing in regex to handle wrapping the 3 in ^3.

Ryan Graham
+4  A: 

Since it is homework, here are some pointers to get you started.

Online Java regex tester

JavaDoc for String.replaceAll method

JavaDoc for the Java regex patterns

TofuBeer
thanks for the resources!
Dan
+2  A: 
import java.util.regex.*;

// (:?\d+) \* x\^(:?\d+)
// 
// Options: ^ and $ match at line breaks
// 
// Match the regular expression below and capture its match into backreference number 1 «(:?\d+)»
//    Match the character “:” literally «:?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single digit 0..9 «\d+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
// Match the character “ ” literally « »
// Match the character “*” literally «\*»
// Match the characters “ x” literally « x»
// Match the character “^” literally «\^»
// Match the regular expression below and capture its match into backreference number 2 «(:?\d+)»
//    Match the character “:” literally «:?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single digit 0..9 «\d+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
try {
    String resultString = subjectString.replaceAll("(?m)(:?\\d+) \\* x\\^(:?\\d+)", "$1x<sup>$2</sup>");
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
} catch (IllegalArgumentException ex) {
    // Syntax error in the replacement text (unescaped $ signs?)
} catch (IndexOutOfBoundsException ex) {
    // Non-existent backreference used the replacement text
}
Lieven
Thanks, that worked great!
Dan
@Dan: Be sure you understand what the regex is doing! Regexes are dangerous in the hands of people who *almost* know them. (Hence the quote I posted.)
Michael Myers
@Dan, as it stands, the regex expects a space in front of and after each *. This can be solved in the regex but let's leave that as an excercise.
Lieven
@mmyers, good point. I'll add comments.
Lieven
@Dan. I changed the regex a bit after creating the comments.Original was: (:?\d+) \* x\^(:?\d)New is: (:?\d+) \* x\^(:?\d+)
Lieven
+1  A: 

If this is for any general math expression and parenthetical expressions are allowed, it will be very difficult (perhaps impossible) to do this with regular expressions.

If the only replacements are the ones you showed, it's not that hard to do. First strip out *'s, then use capturing like Can Berk Güder showed to handle the ^'s.

Michael Myers
Yes, I later explained in a P.S. note that I'm using this to parse a basic string representation of a polynomial into something more human readable.Thanks!
Dan
Polynomials can all be expanded to a form involving no parenthetical expressions. Paren-matching is great fun, though, so you shouldn't limit yourself to expanded form only.
Adam Jaskiewicz
A: 

Try this:

String str = "5 * x^3 - 6 * x^1 + 1";
String replacedStr = str.replaceAll("\\^(\\d+)", "<sup>\$1</sup>");

Be sure to import java.util.regex.

cdmckay
Thanks for the 'import' tip.Unfortunately, Eclipse gives me an error for the second parameter:"Invalid escape sequence"
Dan
Hmmm... I test it in GroovyConsole but not Java. You also have to make sure that this is all in Java boilerplate (i.e. make a class, and throw it in a main method).
cdmckay
Yes, it is... strange.
Dan
The replacement string should be "<sup>$1</sup>" - no backslashes. Groovy has different rules about backslashes; you should test your code in Java.
Alan Moore
+2  A: 

What is your polynomial? If you're "processing" it, I'm envisioning some sort of tree of sub-expressions being generated at some point, and would think that it would be much simpler to use that to generate your string than to re-parse the raw expression with a regex.

Just throwing a different way of thinking out there. I'm not sure what else is going on in your app.

Adam Jaskiewicz
I understand what you're saying... that would indeed spare me a lot of suffering, but I'm trying to keep things separate. I wanted Polynomial to be a stand-alone Class that can be used in other context, such as the console... but my approach might be wrong. What do you think?
Dan
I see what you mean. Incorporating the html tags into Polynomial.toString() is definitely breaking MVC. I think I would still do something like that, though, because it really would make things easier. Perhaps toHtmlString() or something...
Adam Jaskiewicz
Or maybe a separate class that the View uses specifically for formatting the polynomial? Then the Polynomial class itself doesn't need to know anything about the formatting.
Herms
That makes even more sense.
Adam Jaskiewicz
i made a new method: toHTML(); when you think about it, toString() and toHTML() are basically the same thing conceptually, except they employ different rules for formatting;
Dan
Yeah, I don't really like that the view-specific formatting is *in* the object, but it would allow you to use polymorphism to deal with a lot of the logic rather than a giant switch statement in a static utility method. When it comes right down to it, toString() is also view-specific formatting...
Adam Jaskiewicz