Author Topic: strMath() not working propperly  (Read 711 times)

Code: [Select]
function strMath(%str)
{
if(strLen(%str) <= 2)
return;
for(%i=0;%i<getWordCount(%str);%i++)
{
if(%i != 0 && %i != getWordCount(%str))
{
%eq = getWord(%str,%i);
echo(%eq);
%n1 = %i - 1;
%n1 = getWord(%str,%i);
echo(%n1);
%n2 = %i + 1;
%n2 = getWord(%str,%i);
echo(%n2);
if(%n1 * 1 == %n1 && %n2 * 1 == %n2)
{
if(%eq $= "+" || %eq $= "-" || %eq $= "/" || %eq $= "*")
%a += math(%n1,%n2,%eq);
}
}
}
return %a;
}

function math(%n1,%n2,%t)
{
switch$(%t)
{
case "+":
return %n1 + %n2;
case "-":
return %n1 - %n2;
case "/":
return %n1 / %n2;
case "*":
return %n1 / %n2;
default:
return 0;
}
}
This should beable to determine the equations output based off a string.
When i put in
echo(strMath("1 + 2"));
it echo'd
Quote from: console
+
+
+
2
2
2
0

Anyone care to fix?
Thanks

Sorry for spoon-feeding like this, but here I go.

Supported operators:
+, -, *, /, ^ and %.

This can handle things such as:
(5 ^ 3 % (17 + 4)) - 3 - 5 + 7 * (3 % 2)

Even this:
(  5         ^ 3 %    ( 17     +   4)     )   -    3     -5 +7    *(   3 %2  )

Code: [Select]
function strMath( %str )
{
if ( !strLen( %str ) )
{
return 0;
}

%off = 0;

while ( true )
{
%pos = striPos( %str, "(", %off );

if ( %pos < 0 )
{
break;
}

%end = strPosBackwards( %str, ")", %pos );

if ( %end < 0 )
{
continue;
}

%mat = trim( getSubStr( %str, %pos + 1, %end - ( %pos + 1 ) ) );
%str = setSubStr( %str, %pos, %end + 1, strMath( %mat ) );
%off = %end + 1;
}

%str = strReplace( %str, " ", "" );
%mat = "+-*/^%";
%off = 0;
%val = 0;

while ( true )
{
%pos = strPosAny( %str, %mat, %off );

if ( %pos < 0 )
{
break;
}

%prev = strPosAnyBackwards( %str, %mat, %pos );
%next = strPosAny( %str, %mat, %pos + 1 );
%type = getSubStr( %str, %pos, 1 );

if ( %prev < 0 && %next < 0 )
{
%pre = getSubStr( %str, 0, %pos );
%sub = getSubStr( %str, %pos + 1, strLen( %str ) );
%prev = 0;
%next = strLen( %str ) - 1;
}
else if ( %prev < 0 && %next >= 0 )
{
%pre = getSubStr( %str, 0, %pos );
%sub = getSubStr( %str, %pos + 1, %next - ( %pos + 1 ) );
%prev = 0;
%next = %next;
}
else if ( %prev >= 0 && %next < 0 )
{
%pre = getSubStr( %str, %prev, %pos - %prev );
%sub = getSubStr( %str, %pos + 1, strLen( %str ) );
%prev = %prev + 1;
%next = strLen( %str ) - 1;
}
else if ( %prev >= 0 && %next >= 0 )
{
%pre = getSubStr( %str, %prev, %pos - %prev );
%sub = getSubStr( %str, %pos + 1, %next - ( %pos + 1 ) );
%prev = %prev + 1;
%next = %next;
}
else
{
return 0;
}

if ( !strLen( %pre ) || !strLen( %sub ) )
{
%str = setSubStr( %str, %prev, %next, 0 );
continue;
}

switch$ ( %type )
{
case "+": %val = %pre + %sub;
case "-": %val = %pre - %sub;
case "*": %val = %pre * %sub;
case "/": %val = %pre / %sub;
case "^": %val = mPow( %pre, %sub );
case "%": %val = %pre % %sub;
default:
%str = setSubStr( %str, %prev, %next, 0 );
continue;
}

if ( %val $= "1.#INF" || %val $= "-1.#IND" )
{
%val = 0;
}

%str = setSubStr( %str, %prev, %next, %val );
}

return %val;
}

function setSubStr( %str, %start, %len, %val )
{
return getSubStr( %str, 0, %start ) @ %val @ getSubStr( %str, %start + %len, strLen( %str ) );
}

function strPosAny( %str, %list, %offset )
{
if ( !strLen( %str ) || !strLen( %list ) )
{
return -1;
}

if ( !strLen( %offset ) )
{
%offset = 0;
}

%cnt = strLen( %str );

for ( %i = 0 ; %i < %cnt ; %i++ )
{
if ( strPos( %list, getSubStr( %str, %i, 1 ) ) >= 0 )
{
return %i;
}
}

return -1;
}

function strPosBackwards( %str, %char, %offset )
{
if ( !strLen( %str ) || !strLen( %char ) )
{
return -1;
}

if ( !strLen( %offset ) )
{
%offset = 0;
}

for ( %i = strLen( %str ) - 1 - %offset ; %i >= 0 ; %i-- )
{
%chr = getSubStr( %str, %i, 1 );

if ( %chr $= %char )
{
return %i;
}
}

return -1;
}

function strPosAnyBackwards( %str, %list, %offset )
{
if ( !strLen( %str ) || !strLen( %list ) )
{
return -1;
}

if ( !strLen( %offset ) )
{
%offset = 0;
}

for ( %i = strLen( %str ) - 1 - %offset ; %i >= 0 ; %i-- )
{
%chr = getSubStr( %str, %i, 1 );

if ( strPos( %list, %chr ) >= 0 )
{
return %i;
}
}

return -1;
}
« Last Edit: January 16, 2012, 03:35:18 AM by Port »

I made a equation parser a while ago, using it for my chat mathbot ATM.
It works perfectly, and works on bedmas, and is fairly compact and very fast.
It auto-formats the equation to fit it, so as long as it's in a valid math format (number operator number) and all brackets have operators, like "5x(2+2)", it will work, no matter how badly spaced it is. It even does parenthesis's :D

Here's the code: (edited to remove arbritrary-precision math functions i made)
Code: [Select]
function backwards(%a)
{
for(%b=0;%b<strLen(%a);%b+)
%c = getSubStr(%a, %b, 1) @ %c;
return %c;
}
function doEquation(%e)
{
%e = stripChars(%e, " ");
%e = strReplace(%e, "+", " + ");
%e = strReplace(%e, "x", " x ");
%e = strReplace(%e, "/", " / ");
%e = strReplace(%e, "-", " - ");
%e = strReplace(%e, "^", " ^ ");
if(strPos(%e, "(") > -1 && strPos(%e, ")") > 0)
{
%f = backwards(%e);
%start = strPos(%e, "(");
%close = mAbs(strPos(%f, ")") - strLen(%e));
%close2 = mAbs(%close - strLen(%e));
%e = doEquation(stripTrailingSpaces(getSubStr(%e, %start + 1, %close - 2))) @ getSubStr(%e, strLen(%e) - %close2, strLen(%e) - (strLen(%e) - %close2));
}
for(%a=0;%a<getWordCount(%e);%a++)
{
if(getWord(%e, %a) $= "^" && %a != 0)
{
%f = getWord(%e, %a-1);
%l = getWord(%e, %a+1);
%e = setWord(%e, %a, mPow(%f, %l));
%e = removeWord(removeWord(%e, %a+1), %a-1);
%a = %a - 2;
}
}
for(%a=0;%a<getWordCount(%e);%a++)
{
if(getWord(%e, %a) $= "x" || getWord(%e, %a) $= "/" && %a != 0)
{
%f = getWord(%e, %a - 1);
%l = getWord(%e, %a + 1);
%o = getWord(%e, %a);
switch$(%o)
{
case "x":
%e = setWord(%e, %a, %f * %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
case "/":
%e = setWord(%e, %a, %f / %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
}
}
}
for(%a=0;%a<getWordCount(%e);%a++)
{
if(getWord(%e, %a) $= "+" || getWord(%e, %a) $= "-" && %a != 0)
{
%f = getWord(%e, %a - 1);
%l = getWord(%e, %a + 1);
%o = getWord(%e, %a);
switch$(%o)
{
case "+":
%e = setWord(%e, %a, %f + %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
case "-":
%e = setWord(%e, %a, %f - %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
}
}
}
return %e;
}
« Last Edit: January 16, 2012, 12:27:26 PM by Ipquarx »

Sorry for spoon-feeding like this, but here I go.

Supported operators:
+, -, *, /, ^ and %.

This can handle things such as:
(5 ^ 3 % (17 + 4)) - 3 - 5 + 7 * (3 % 2)

Even this:
(  5         ^ 3 %    ( 17     +   4)     )   -    3     -5 +7    *(   3 %2  )

Code: [Select]
-snip-
Thanks :)

I made a equation parser a while ago, using it for my chat mathbot ATM.
It works perfectly, and works on bedmas, and is fairly compact and very fast.
It auto-formats the equation to fit it, so as long as it's in a valid math format (number operator number) and all brackets have operators, like "5x(2+2)", it will work, no matter how badly spaced it is. It even does parenthesis's :D

Here's the code: (edited to remove arbritrary-precision math functions i made)
Code: [Select]
-snip-

You too :)
idk why you put in a backwards function though.

To find the last closing parenthesis.

Trust me, it's a fully functional recursive-looping equation parser, and it's easy to add even more operators.
It's fairly short compared to port's and as it looks, quite a bit more memory/processing-power efficiant.

It's fairly short compared to port's and as it looks, quite a bit more memory/processing-power efficiant.

Well yeah, it wasn't really that well written and was done in a rush (~6 minutes).

If you're wondering the recursive part of mine is, it's the parenthesis's.
The first IF statement has that.

Port's causes an infinite loop due to sub string errors, and Ipquarx's has a syntax error on line 3.

Port's causes an infinite loop due to sub string errors, and Ipquarx's has a syntax error on line 3.
I just noticed that thank you (but it was on line 2, forgot a +), and also a parenthesis error.
This is the fixed version:
Code: [Select]
function doEquation(%e)
{
%e = stripChars(%e, " ");
%old = %e;
%e = strReplace(%e, "+", " + ");
%e = strReplace(%e, "x", " x ");
%e = strReplace(%e, "/", " / ");
%e = strReplace(%e, "-", " - ");
%e = strReplace(%e, "^", " ^ ");
if(%e $= %old)
return %e;
while(strPos(%e, "(") != false && strPos(%e, ")") > 0)
{
%start = strPos(%e, "(");
%end = %start;
%level = 1;
while(%level != 0 && %end != strLen(%e))
{
%end++;
if(getsubStr(%e, %end, 1) $= "(")
%level++;
if(getsubStr(%e, %end, 1) $= ")")
%level--;
}
%e = getsubStr(%e, 0, %start) @ doEquation(getsubStr(%e, %start+1, %end - strLen(getsubStr(%e, 0, %start + 1)))) . getsubStr(%e, %end + 1, strLen(%e) - %end);
}
for(%a=0;%a<getWordCount(%e);%a++)
{
if(getWord(%e, %a) $= "^" && %a != 0)
{
%f = getWord(%e, %a-1);
%l = getWord(%e, %a+1);
%e = setWord(%e, %a, mPow(%f, %l));
%e = removeWord(removeWord(%e, %a+1), %a-1);
%a = %a - 2;
}
}
for(%a=0;%a<getWordCount(%e);%a++)
{
if(getWord(%e, %a) $= "x" || getWord(%e, %a) $= "/" && %a != 0)
{
%f = getWord(%e, %a - 1);
%l = getWord(%e, %a + 1);
%o = getWord(%e, %a);
switch%(%o)
{
case "x":
%e = setWord(%e, %a, %f * %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
case "/":
%e = setWord(%e, %a, %f / %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
}
}
}
for(%a=0;%a<getWordCount(%e);%a++)
{
if(getWord(%e, %a) $= "+" || getWord(%e, %a) $= "-" && %a != 0)
{
%f = getWord(%e, %a - 1);
%l = getWord(%e, %a + 1);
%o = getWord(%e, %a);
switch%(%o)
{
case "+":
%e = setWord(%e, %a, %f + %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
case "-":
%e = setWord(%e, %a, %f - %l);
%e = removeWord(%e, %a + 1);
%e = removeWord(%e, %a - 1);
%a = %a - 2;
}
}
}
return %e;
}
I also put a PHP version of this online at http://ipmath.hostzi.com/equation.php?in= (enter a equation without any spaces here)
« Last Edit: January 17, 2012, 01:47:41 PM by Ipquarx »