[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 231
  • Last Modified:

A regular expression to find equations

Hello people,
I am trying to write a regular expression that will look in a string and determine which parts of the string are equations. For example:

Hello this is 2+3 an equation and 1-2+1-3 is one too as well as (1+2-4) but I'm afraid ( 1 / 2 *(1+2)) is an equation too.

This would return 2+3 1-2+1-3 (1+2-4) and ( 1 / 2 *(1+2)).

Numbers may or may not have spaces between them. The symbols are + - * /. Also mind the parentheses. Any ideas? Most of my attempts have failed up to now.

Thank you very much.

Deleted by ee_ai_construct, 500 points refunded. - 11/15/2004 4:30:25 PM PST
0
theplasma
Asked:
theplasma
  • 3
  • 3
  • 2
  • +2
1 Solution
 
stefan73Commented:
Hi theplasma,
I don't think you can do this as a regex - the problem is to store the nesting level somehow.

You need something like Yacc to check it properly.

Cheers!

Stefan
0
 
manav_mathurCommented:
1) Do we have to do parantheses matching also??
2) is "1" an equation too??

I have devised a primitive technique which takes care of simple equations like 1+2 or 1+2+3 or 1+2+3-4.

This successively removes froma a string the last "symbol+digit". In the end, if only a single digit remains, it is a balanced equation. (thats my assumption)

use strict;
use warnings;
my $var="1" ;
while ($var =~ m/^.*([\+\-\/\*]\d)$/) {
print "Matched : $1\n";
my $temp=quotemeta $1;
$var =~ s/$temp//;
print "$var\n" ;
}
if ($var =~ /^\d$/) {print "Found" ;}
else { print "Nofound" ;}


Manav
0
 
manav_mathurCommented:
sorry,

this version takes care of multidigit numbers occuring in the string

use strict;
use warnings;
my $var="1" ;
while ($var =~ m/^.*([\+\-\/\*]\d)$/) {
print "Matched : $1\n";
my $temp=quotemeta $1;
$var =~ s/$temp//;
print "$var\n" ;
}
if ($var =~ /^\d+$/) {print "Found" ;}
else { print "Nofound" ;}

Manav

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
manav_mathurCommented:
Sorry,
misread the question
this is a way to test whether a string is an equation or not. :(

Manav
0
 
gripeCommented:
Homework. :P
0
 
theplasmaAuthor Commented:
nevermind I figured it out, thanks anyway manav.
0
 
stefan73Commented:
gripe,
Yep.

theplasma: Think about some basic rules for an equation. This will be:

1. All equations must only consist of parantheses, digits or operators.
2. The number of closing parantheses must be equal to the number of opening parantheses.
3. Each binary operator must have either a digit or an opening parathesis to its right.
4. Each binary operator must have either a digit or a closing parathesis to its left.

This is not yet sufficient to express validy of parenthesis nesting, but should be a good pre-filter for faulty equations.

And get rid of these spaces first.

Stefan
0
 
ozoCommented:
$_ = "Hello this is 2+3 an equation and 1-2+1-3 is one too as well as (1+2-4) but I'm afraid ( 1 / 2 *(1+2)) is an equation too.";
for( grep{ /\d/ && !m([(*/+-]\s*[*/)]) && !/\d\s+\d/ &&((my $r=$_) =~ tr/()//cd, eval{qr/$r/}, !$@)}/([-+*\/()\s\d]+)/g ){
    print "$_\n";
}
0
 
ozoCommented:
What was the solution you figured out?
0
 
theplasmaAuthor Commented:
ozo, since you asked, the regular expression I used is:
[\s]*[(]*([(]*[-+]?\d+(\.\d+)?[)]*[\s]*([\+\-\*\/]{1}[\s]*[(]*[-+]?\d+(\.\d+)?[)]*)+[)]*[\+\-\*\/]?)+[\s]*
which pretty much does the trick, don't you think?
0
 
ozoCommented:
 ( 1 / 2 *(1+2)) is an equation too
but your espression returns
1 / 2
and
(1+2))
instead of
( 1 / 2 *(1+2))
also
1 + 2 * 3 + 4 * 5
returns
1 + 2
3 + 4
missing the 5
1 + ( 2 * 3 )
misses the 1
it also doesn't find
(9)
and
(((1+2)))
returns
1+2)))
and 1)+(2 is not an equation, but you permit it


I didn't realize you wanted to permit numbers like 1.2, so my modified pattern is
for( grep{ /\d/&&!/\.\D|\D\./&&!m([(*/+-]\s*[*/)])&&!/\d\s+\d/ &&(($r=$_)=~tr/()//cd, eval{qr/$r/}, !$@)}/([-+*\/().\s\d]+)/g ){
    print "$_\n";
}
If you require at least one of [-+*/], add
for( grep{ /\d/&&/[-+\/*]/&&!/\.\D|\D\./&&!m([(*/+-]\s*[*/)])&&!/\d\s+\d/ &&(($r=$_)=~tr/()//cd, eval{qr/$r/}, !$@)}/([-+*\/().\s\d]+)/g ){
    print "$_\n";
}
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 3
  • 3
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now