Sign in to follow this  
Followers 0
AutID

Analyse math calculations

16 posts in this topic

I am not sure how to explain this so I will show

Local $eq = (8 + (7 * 4) - (3 *(2 / 7)))
ConsoleWrite($eq & @LF)

;       Calculation of equation
;       (8 + (7 * 4) - (3 *(2 / 7)))
;       (8 + 28) - (3 * 0.2857142857142857)
;        36 - 0.8571428571428571

I could write a small function if the equation I am dealing with would be a standard one but there are thousands of equations.
So I would have to analyse all of them and then return some results. Anyone ever heard of a DLL or an UDF that is capable to do this?

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

I will be handling math calculations such as the one in post 1, or different. For autoit it is easy to retrieve the results. However I want to analyse how we got the result. To see how it is done. How the calculation is done, how the entire process is done.

Something like this I suppose

Edit: let me put the code together

#include <Array.au3>
Local $eq = (8 + (7 * 4) - (3 *(2 / 7)))
ConsoleWrite($eq & @LF)
Local $eq2 = _EquationAnalysedResult($eq)
If IsArray($eq2) Then _ArrayDisplay($eq2)
 
 
Func _EquationAnalysedResult($equation)
 
;  do the calculation
;  Calculation of equation
;  (8 + (7 * 4) - (3 *(2 / 7)))
;  (8 + 28) - (3 * 0.2857142857142857)
;   36 - 0.8571428571428571
;  return an array with the entire process as above
 Return $equation
EndFunc
Edited by AutID

Share this post


Link to post
Share on other sites

Basically an equation is two expressions which are numerically equal, and the possibilities are endless. I remember Mat did some factorization (with quadratics - I think), but that was quite a while ago. Looking at your example, I see you can remove all the brackets and still get the same answer. There's a clue in there somewhere. :think:

Share this post


Link to post
Share on other sites

You basically need to show the precedence as it is being executed highest to lowest as in the help file, correct?

 

From highest precedence to lowest:

    Not
    ^
    * /
    + -
    &
    < > <= >= = <> ==

    And Or


Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

You basically need to show the precedence as it is being executed highest to lowest as in the help file, correct?

Yes if I am understanding that correctly.

Edit: Like in the post 3.

Edited by AutID

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Dividing into order of operations seems wayyyy difficult.   Simplifying sections between operators much less so,but still probably a thousand edge cases to break it.

--Use wolfram to do your homework like everyone else :)

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

Does seem hard, this would be an approach to grab all the unique parens operations (convert to a string and then parse):

#include <Array.au3>
#include <String.au3>
$eq = "(8 + (7 * 4) - (3 *(2 / 7)))"
func _parseEquation($eq)
    $parens=_StringBetween ($eq,"(",")")
    for $a=0 to ubound($parens) -1
        $parens[$a]&=")"
    next
    _ArrayDisplay($parens)
EndFunc
_parseEquation($eq)

But that still leaves a lot of work to be done to grab all the operators in the order of precedence.   It is a start ...


Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

I'm sure there are many ways to break this (especially considering I only did add/subtract/division/multiplication), I'll leave it to you all to break it.

Edit:

Found another breaking point lol, I'm done looking :P

#include <Array.au3>

Global $gsz_equation = "(8 + (7 * 4) - (3 *(2 / 7)))"
Global $ga_ret = _ProcessSimpleEquation($gsz_equation)
_ArrayDisplay($ga_ret)

; to console
For $i = 1 To UBound($ga_ret) - 1
    ConsoleWrite($ga_ret[$i] & @CRLF)
Next

Func _ProcessSimpleEquation($s_eq)

    $s_eq = StringReplace($s_eq, " ", "")

    Local $s_tmp = $s_eq, $a_tmp
    Local $s_ret =  StringRegExpReplace($s_eq, "(\+|\-|\*|/)", " $1 ") & @LF

    ; get mult/div with digits on both sides
    $a_tmp = StringRegExp($s_tmp, "((?:\d*\.?\d*)(?<=\d)[\*/](?:\d*\.?\d*))", 3)
    If Not @error Then
        For $i = 0 To UBound($a_tmp) - 1
            $s_tmp = StringRegExpReplace($s_tmp, "\b\Q" & $a_tmp[$i] & "\E\b", Execute($a_tmp[$i]))
        Next
        ; format string
        $s_ret &= StringRegExpReplace($s_tmp, "(\+|\-|\*|/)", " $1 ") & @LF
    EndIf

    ; get mult/div from possible parenth left over
    $a_tmp = StringRegExp($s_tmp, "(\(?(?:\d*\.?\d*)(?<=\d)[\*/]\(?(?:\d*\.?\d*))", 3)
    If Not @error Then
        ; add parenthesis
        For $i = 0 To UBound($a_tmp) -1
            StringReplace($a_tmp[$i], "(", "")
            For $j = 2 To @extended
                $a_tmp[$i] &= ")"
            Next
            $a_tmp[$i] = StringTrimLeft($a_tmp[$i], 1)
            $s_tmp = StringRegExpReplace($s_tmp, "\Q" & $a_tmp[$i] & "\E", Execute($a_tmp[$i]))
        Next
        ; format string
        $s_ret &= StringRegExpReplace($s_tmp, "(\+|\-|\*|/)", " $1 ") & @LF
    EndIf

    ; on to addition/subtraction
    While 1
        $a_tmp = StringRegExp($s_tmp, "((?:\d*\.?\d*)(?<=\d)[\-\+]\(?(?:\d*\.?\d*)(?<=\d)\)?)", 3)
        If @error Then ExitLoop
        For $i = 0 To UBound($a_tmp) - 1
            $s_tmp = StringRegExpReplace($s_tmp, "\Q" & $a_tmp[$i] & "\E", Execute($a_tmp[$i]))
        Next
        ; format string
        $s_ret &= StringRegExpReplace($s_tmp, "(\+|\-|\*|/)", " $1 ") & @LF
    WEnd

    ; we are going to return an array
    $a_tmp = StringSplit(StringTrimRight($s_ret, 1), @LF)
    $a_tmp[$a_tmp[0]] = Execute($a_tmp[$a_tmp[0]])

    Return $a_tmp
EndFunc

..

Edited by SmOke_N
1 person likes this

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Assuming parenthesis are placed with art and correctly  :D

something like this should work

$eq = "(8 + (7 * 4)) - (3 *(2 / 7))"

$res = $eq & @crlf&@crlf
StringReplace($eq, "(", "")
$p1 = @extended
StringReplace($eq, ")", "")
$p2 = @extended
If $p1<>$p2 Then Exit Msgbox(0,"", "parenthesis error")

For $i = 1 to $p1
   $sub = (Mod($i, 2)=0) ? StringRegExpReplace($eq, '.*(\([^\(\)]*?\)).*?\)*', '$1') : _
                    StringRegExpReplace($eq, '.*?(\([^\(\)]*?\)).*', '$1')
   $eq = StringReplace($eq, $sub, Execute($sub) )
   $res &= $eq & @crlf
Next
$res &= Execute($eq)
Msgbox(0,"", $res)

Edit

and using operators precedence

Edited by mikell

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Nice

Edit:

Mikell, I remember why I stopped doing a similar approach.

For $eq, use something like 8 + 9 * 3, without parenthesis.

I believe the OP wanted to see the break down of the math itself, not just the answer(s).

Edit2:

Alas, mine doesn't process without parenthesis with an equation like: 8 + 9 * 3 * 4 either.

Edited by SmOke_N

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

First of all thanks to everyone for the help.

I would try it with >shunting-yard-algorithm.
 
Br,
UEZ

hmmm, I am not sure it could help me with a quick look I had. May get deeper into that.

I'm sure there are many ways to break this (especially considering I only did add/subtract/division/multiplication), I'll leave it to you all to break it.

Edit:

Found another breaking point lol, I'm done looking :P

#include <Array.au3>

Global $gsz_equation = "(8 + (7 * 4) - (3 *(2 / 7)))"
Global $ga_ret = _ProcessSimpleEquation($gsz_equation)
_ArrayDisplay($ga_ret)

; to console
For $i = 1 To UBound($ga_ret) - 1
    ConsoleWrite($ga_ret[$i] & @CRLF)
Next

Func _ProcessSimpleEquation($s_eq)

    $s_eq = StringReplace($s_eq, " ", "")

    Local $s_tmp = $s_eq, $a_tmp
    Local $s_ret =  StringRegExpReplace($s_eq, "(\+|\-|\*|/)", " $1 ") & @LF

    ; get mult/div with digits on both sides
    $a_tmp = StringRegExp($s_tmp, "((?:\d*\.?\d*)(?<=\d)[\*/](?:\d*\.?\d*))", 3)
    If Not @error Then
        For $i = 0 To UBound($a_tmp) - 1
            $s_tmp = StringRegExpReplace($s_tmp, "\b\Q" & $a_tmp[$i] & "\E\b", Execute($a_tmp[$i]))
        Next
        ; format string
        $s_ret &= StringRegExpReplace($s_tmp, "(\+|\-|\*|/)", " $1 ") & @LF
    EndIf

    ; get mult/div from possible parenth left over
    $a_tmp = StringRegExp($s_tmp, "(\(?(?:\d*\.?\d*)(?<=\d)[\*/]\(?(?:\d*\.?\d*))", 3)
    If Not @error Then
        ; add parenthesis
        For $i = 0 To UBound($a_tmp) -1
            StringReplace($a_tmp[$i], "(", "")
            For $j = 2 To @extended
                $a_tmp[$i] &= ")"
            Next
            $a_tmp[$i] = StringTrimLeft($a_tmp[$i], 1)
            $s_tmp = StringRegExpReplace($s_tmp, "\Q" & $a_tmp[$i] & "\E", Execute($a_tmp[$i]))
        Next
        ; format string
        $s_ret &= StringRegExpReplace($s_tmp, "(\+|\-|\*|/)", " $1 ") & @LF
    EndIf

    ; on to addition/subtraction
    While 1
        $a_tmp = StringRegExp($s_tmp, "((?:\d*\.?\d*)(?<=\d)[\-\+]\(?(?:\d*\.?\d*)(?<=\d)\)?)", 3)
        If @error Then ExitLoop
        For $i = 0 To UBound($a_tmp) - 1
            $s_tmp = StringRegExpReplace($s_tmp, "\Q" & $a_tmp[$i] & "\E", Execute($a_tmp[$i]))
        Next
        ; format string
        $s_ret &= StringRegExpReplace($s_tmp, "(\+|\-|\*|/)", " $1 ") & @LF
    WEnd

    ; we are going to return an array
    $a_tmp = StringSplit(StringTrimRight($s_ret, 1), @LF)
    $a_tmp[$a_tmp[0]] = Execute($a_tmp[$a_tmp[0]])

    Return $a_tmp
EndFunc

..

Smoke try adding one more parenthesis to the equation. I said the equation will be similar as the one in post on but not exactly the same. Your example is very good and will work very good with the same number of parenthesis or less, but not with more.
I could fix it but I understand nothing about regex, it is simply beyond my head so quitted long time ago.

Assuming parenthesis are placed with art and correctly  :D

something like this should work

$eq = "(8 + (7 * 4)) - (3 *(2 / 7))"

$res = $eq & @crlf&@crlf
StringReplace($eq, "(", "")
$p1 = @extended
StringReplace($eq, ")", "")
$p2 = @extended
If $p1<>$p2 Then Exit Msgbox(0,"", "parenthesis error")

For $i = 1 to $p1
   $sub = (Mod($i, 2)=0) ? StringRegExpReplace($eq, '.*(\([^\(\)]*?\)).*?\)*', '$1') : _
                    StringRegExpReplace($eq, '.*?(\([^\(\)]*?\)).*', '$1')
   $eq = StringReplace($eq, $sub, Execute($sub) )
   $res &= $eq & @crlf
Next
$res &= Execute($eq)
Msgbox(0,"", $res)

Edit

and using operators precedence

This seems to work very good actually. It will give a good result with a lot of different equations I tried however the break down isn't so accurate.
Try this and check the break down, "(8 + (7 * 4)) - (3 - (9 * 3) *(2 / (7 * 7)))"

Share this post


Link to post
Share on other sites

Well, I went cross-eyed with the regex, and went back old school.

I can see it breaking if the math fails (if values exceed scope).

Global $ga_Equation[4] = [ _
    "(8 + (7 * ((3 / 4) * (5 / (2 ^ (4 ^ 2))))))", _
    "8 + 7 * 3 / 4 * 5 / 2 ^ 2 ^ 2", _
    "8 + (7 * ((3 / 4) * (5 / (4 ^ 2))))", _
    "8 + 7 * 4 - 3 *2 / 7 + 2^3"]

Global $ga_Arr = 0

For $i = 0 To UBound($ga_Equation) - 1
    $ga_Arr = _getMathBreakDown($ga_Equation[$i])
    _simpleArray2Cons($ga_Arr, 1)
    ConsoleWrite("----" & @CRLF)
Next

Func _getMathBreakDown($s_str)

    Local $s_ret = $s_str

    While 1
        $s_tmp = __getParenthesisItems($s_str)
        If @error Then ExitLoop
        $s_str = StringRegExpReplace($s_str, "\Q" & $s_tmp & "\E", Execute($s_tmp), 1)
        $s_ret &=  @LF & $s_str
    WEnd

    Local $a_ret
    If $s_ret = $s_str Then
        ; we don't want to assume how they want to process
        ;  the numbers sent, so parenthesis are their responsibility
        ;  however, if they sent something with no parenthesis
        ;  it might be fun to show them what the break down is like
        ;  from the programs translator
        ; Order:
        ;  ^, /, *, +, -
        ; recursion fun!!! :)
        $a_ret = _getMathBreakDown(_setParenthesisMathItems($s_str))
        $s_ret = $s_str
        For $i = 1 To UBound($a_ret) - 1
            If StringLen($a_ret[$i]) Then $s_ret &= @LF & $a_ret[$i]
        Next
        $s_str = $a_ret[UBound($a_ret)-1]
    EndIf

    If Not StringRegExp($s_str, "^(\d+\.?\d*|\d*\.?\d+)\z") Then
        $s_ret &= @LF & Execute($s_str)
    EndIf

    $a_ret = StringSplit($s_ret, @LF)
    Return $a_ret
EndFunc

Func _setParenthesisMathItems($s_str)

    Local Const $a_items[] = ["^","/","*","+","-"]
    Local $s_tmp = $s_str

    Local $a_ret[100][2], $a_tmp, $i_cc = 0
    For $i = 0 To UBound($a_items) - 1
        $a_tmp = __setParenthesisMathItems($s_str, $a_items[$i])
        If Not @error Then
            If Mod($i_cc + 1, 100) = 0 Then
                ReDim $a_ret[$i_cc + 101][2]
            EndIf
            For $n = 0 To UBound($a_tmp) - 1
                $a_ret[$i_cc][0] = $a_tmp[$n][0]
                $a_ret[$i_cc][1] = $a_tmp[$n][1]
                $i_cc += 1
            Next
        EndIf
    Next
    ReDim $a_ret[$i_cc][2]

    If $s_str = $s_tmp Then
        ; error???
        Return SetError(1, 0, $s_tmp)
    EndIf

    For $i = UBound($a_ret) - 1 To 0 Step - 1
        $s_str = StringReplace($s_str, $a_ret[$i][0], $a_ret[$i][1], 1, 1)
    Next

    Return $s_str
EndFunc

Func __setParenthesisMathItems(ByRef $s_str, $s_item)

    Local Const $a_items[] = ["^","/","*","+","-"]
    Local Const $a_repitems[] = ["p","d","m","a","s"]
    Local $s_repl = ""
    For $i = 0 To UBound($a_items) - 1
        If $s_item = $a_items[$i] Then
            $s_repl = "rep" & $a_repitems[$i]
            ExitLoop
        EndIf
    Next

    StringReplace($s_str, $s_item, "")
    Local $n_items = @extended

    If Not $n_items Then
        Return SetError(1, 0, 0)
    EndIf

    Local $a_temp = 0, $s_last, $a_reg, $n_ub
    Local $i_cc = 0, $s_repn = "", $s_tmp = $s_str
    While 1
        $a_reg = StringRegExp($s_str, "((?:\d*\.?\d+|\d+\.?\d*|rep.\d+)\s*\" & $s_item & "\s*)", 3)
        If @error Then ExitLoop
        $n_ub = UBound($a_reg) - 1
        $a_temp = StringRegExp($s_str, "(\Q" & $a_reg[$n_ub] & "\E(?:\d*\.?\d+|\d+\.?\d*|rep.\d+))", 3)
        If @error Then ExitLoop
        $s_str = StringReplace($s_str, $a_temp[0], $s_repl & $i_cc, -1, 1)
        $s_repn &= "(" & $a_temp[0] & ")|" & $s_repl & $i_cc & @LF
        $i_cc += 1
    WEnd

    If $s_str = $s_tmp Then
        Return SetError(2, 0, 0)
    EndIf

    Local $a_split = StringSplit(StringTrimRight($s_repn, 1), @LF, 2)
    Local $a_ret[UBound($a_split)][2], $i_cc = 0
    For $i = 0 To UBound($a_split) - 1
        $a_tmp = StringSplit($a_split[$i], "|")
        $a_ret[$i][0] = $a_tmp[2]
        $a_ret[$i][1] = $a_tmp[1]
    Next

    Return $a_ret
EndFunc

Func __getParenthesisItems($s_str)

    StringReplace($s_str, "(", "")
    Local $n_parenthesis = @extended
    If Not $n_parenthesis Then
        Return SetError(1, 0, 0)
    EndIf

    StringReplace($s_str, ")", "")
    If @extended <> $n_parenthesis Then
        Return SetError(1, 0, 0)
    EndIf

    Local $s_tmp
    Local $i_lftpos = 0, $i_rgtpos = 0
    $i_lftpos = StringInStr($s_str, "(", 0, $n_parenthesis)
    $s_tmp = StringTrimLeft($s_str, $i_lftpos - 1)
    $i_rgtpos = StringInStr($s_tmp, ")", 0, 1)
    Return StringMid($s_str, $i_lftpos, $i_rgtpos)
EndFunc

Func _simpleArray2Cons(ByRef $a_arr, $n_istart = 0, $n_jstart = 0)

    Local $n_ub1 = UBound($a_arr)
    If $n_ub1 = 0 Then Return SetError(1)

    Local $n_ub2 = UBound($a_arr, 2)
    Local $s_toconsole

    If $n_ub2 Then
        For $i = $n_istart To $n_ub1 - 1
            For $j = $n_jstart To $n_ub2 - 1
                $s_toconsole &= "[" & $i & "][" & $j & "] = " & $a_arr[$i][$j] & @CRLF
            Next
            ConsoleWrite($s_toconsole)
            $s_toconsole = ""
        Next
        Return
    EndIf

    For $i = $n_istart To $n_ub1 - 1
        $s_toconsole &= "[" & $i & "] = " & $a_arr[$i] & @CRLF
    Next
    ConsoleWrite($s_toconsole)
EndFunc
1 person likes this

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

And yet more... had to format those strings that didn't have all the brackets correctly ... and this stupid string obsession is over... if you find the errors, you fix'em ;)

Global $ga_Equation[] = [ _
    "(8 + (7 * 4) - (3 *(2 / 7)))", _
    "8 + 7 * 4 - 3 * 2 / 7", _
    "8 + 7 * (4 - 3) * 2 / 7"]

Global $ga_Arr = 0

For $i = 0 To UBound($ga_Equation) - 1
    $ga_Arr = _getMathBreakDown($ga_Equation[$i])
    _simpleArray2Cons($ga_Arr, 1)
    ConsoleWrite("----" & @CRLF)
Next

Func _getMathBreakDown($s_str)

    Local $s_ret = $s_str
    Local $s_hold = $s_str
    Local $s_tmp = __formatMathBreakDown($s_str)
    If $s_tmp <> $s_str Then
        $s_ret &= @LF & $s_tmp
        $s_str = $s_tmp
    EndIf

    While 1
        $s_tmp = __getParenthesisItems($s_str)
        If @error Then ExitLoop
        $s_str = StringRegExpReplace($s_str, "\Q" & $s_tmp & "\E", Execute($s_tmp), 1)
        $s_ret &=  @LF & $s_str
    WEnd

    Local $a_ret
    StringRegExpReplace($s_str, "[\*\-\+\^/]", "")
    If @extended > 1 Or $s_ret = $s_str Then
        ; we don't want to assume how they want to process
        ;  the numbers sent, so parenthesis are their responsibility
        ;  however, if they sent something with no parenthesis
        ;  it might be fun to show them what the break down is like
        ;  from the programs translator
        ; Order:
        ;  ^, /, *, +, -
        ; recursion fun!!! :)
        $a_ret = _getMathBreakDown(_setParenthesisMathItems($s_str))
        $s_ret = $s_hold <> $s_str ? $s_hold & @LF & $s_str : $s_str
        For $i = 1 To UBound($a_ret) - 1
            If StringLen($a_ret[$i]) Then $s_ret &= @LF & $a_ret[$i]
        Next
        $s_str = $a_ret[UBound($a_ret)-1]
    EndIf

    If Not StringRegExp($s_str, "^(\d+\.?\d*|\d*\.?\d+)\z") Then
        $s_ret &= @LF & Execute($s_str)
    EndIf

    $a_ret = StringSplit($s_ret, @LF)
    Return $a_ret
EndFunc

Func _setParenthesisMathItems($s_str)

    Local Const $a_items[] = ["^","/","*","+","-"]
    Local $s_tmp = $s_str

    Local $a_ret[100][2], $a_tmp, $i_cc = 0
    For $i = 0 To UBound($a_items) - 1
        $a_tmp = __setParenthesisMathItems($s_str, $a_items[$i])
        If Not @error Then
            If Mod($i_cc + 1, 100) = 0 Then
                ReDim $a_ret[$i_cc + 101][2]
            EndIf
            For $n = 0 To UBound($a_tmp) - 1
                $a_ret[$i_cc][0] = $a_tmp[$n][0]
                $a_ret[$i_cc][1] = $a_tmp[$n][1]
                $i_cc += 1
            Next
        EndIf
    Next
    ReDim $a_ret[$i_cc][2]

    If $s_str = $s_tmp Then
        ; error???
        Return SetError(1, 0, $s_tmp)
    EndIf

    For $i = UBound($a_ret) - 1 To 0 Step - 1
        $s_str = StringReplace($s_str, $a_ret[$i][0], $a_ret[$i][1], 1, 1)
    Next

    Return $s_str
EndFunc

Func __setParenthesisMathItems(ByRef $s_str, $s_item)

    Local Const $a_items[] = ["^","/","*","+","-"]
    Local Const $a_repitems[] = ["p","d","m","a","s"]
    Local $s_repl = ""
    For $i = 0 To UBound($a_items) - 1
        If $s_item = $a_items[$i] Then
            $s_repl = "rep" & $a_repitems[$i]
            ExitLoop
        EndIf
    Next

    StringReplace($s_str, $s_item, "")
    Local $n_items = @extended

    If Not $n_items Then
        Return SetError(1, 0, 0)
    EndIf

    Local $a_temp = 0, $s_last, $a_reg, $n_ub
    Local $i_cc = 0, $s_repn = "", $s_tmp = $s_str
    While 1
        $a_reg = StringRegExp($s_str, "((?:\d*\.?\d+|\d+\.?\d*|rep.\d+)\s*\" & $s_item & "\s*)", 3)
        If @error Then ExitLoop
        $n_ub = UBound($a_reg) - 1
        $a_temp = StringRegExp($s_str, "(\Q" & $a_reg[$n_ub] & "\E(?:\d*\.?\d+|\d+\.?\d*|rep.\d+))", 3)
        If @error Then ExitLoop
        $s_str = StringReplace($s_str, $a_temp[0], $s_repl & StringFormat("%04d", $i_cc), -1, 1)
        $s_repn &= "(" & $a_temp[0] & ")|" & $s_repl & StringFormat("%04d", $i_cc) & @LF
        $i_cc += 1
    WEnd

    If $s_str = $s_tmp Then
        Return SetError(2, 0, 0)
    EndIf

    Local $a_split = StringSplit(StringTrimRight($s_repn, 1), @LF, 2)
    Local $a_ret[UBound($a_split)][2], $i_cc = 0
    For $i = 0 To UBound($a_split) - 1
        $a_tmp = StringSplit($a_split[$i], "|")
        $a_ret[$i][0] = $a_tmp[2]
        $a_ret[$i][1] = $a_tmp[1]
    Next

    Return $a_ret
EndFunc

Func __getParenthesisItems($s_str)

    StringReplace($s_str, "(", "")
    Local $n_parenthesis = @extended
    If Not $n_parenthesis Then
        Return SetError(1, 0, 0)
    EndIf

    StringReplace($s_str, ")", "")
    If @extended <> $n_parenthesis Then
        Return SetError(1, 0, 0)
    EndIf

    Local $s_tmp
    Local $i_lftpos = 0, $i_rgtpos = 0
    $i_lftpos = StringInStr($s_str, "(", 0, $n_parenthesis)
    $s_tmp = StringTrimLeft($s_str, $i_lftpos - 1)
    $i_rgtpos = StringInStr($s_tmp, ")", 0, 1)
    Return StringMid($s_str, $i_lftpos, $i_rgtpos)
EndFunc

Func __formatMathBreakDown($s_str)

    $s_str = StringStripWS($s_str, 7)

    Local $s_change = $s_str, $s_out
    Local $i_cc = 0, $i_ub
    Local $a_tmp, $a_tmp2, $a_split
    If StringInStr($s_str, "(", 1, 1) Then
        While 1
            $s_tmp = __getParenthesisItems($s_change)
            If @error Then ExitLoop
            $s_change = StringReplace($s_change, $s_tmp, "rep" & StringFormat("%04d", $i_cc))
            $s_out &= $s_tmp & "|" & "rep" & StringFormat("%04d", $i_cc) & @LF
            $i_cc += 1
        WEnd
        $a_tmp = StringSplit(StringTrimRight($s_out, 1), @LF)
        Dim $a_tmp2[UBound($a_tmp) - 1][2]
        $i_ub = UBound($a_tmp2)
        For $i = 1 To UBound($a_tmp) - 1
            $a_split = StringSplit($a_tmp[$i], "|")
            $a_tmp2[$i - 1][0] = $a_split[2]
            $a_tmp2[$i - 1][1] = $a_split[1]
        Next
        StringRegExpReplace($a_tmp2[$i_ub-1][1], "[\*\-\+\^/]", "")
        If @extended > 1 Then
            $a_tmp2[$i_ub - 1][1] = _setParenthesisMathItems( _
                StringRegExpReplace($a_tmp2[$i_ub - 1][1], "\(|\)", ""))
        EndIf
        For $i = UBound($a_tmp2) - 1 To 0 Step -1
            $s_change = StringReplace($s_change, $a_tmp2[$i][0], $a_tmp2[$i][1])
        Next
        Return $s_change
    EndIf

    Return _setParenthesisMathItems($s_str)
EndFunc

Func _simpleArray2Cons(ByRef $a_arr, $n_istart = 0, $n_jstart = 0)

    Local $n_ub1 = UBound($a_arr)
    If $n_ub1 = 0 Then Return SetError(1)

    Local $n_ub2 = UBound($a_arr, 2)
    Local $s_toconsole

    If $n_ub2 Then
        For $i = $n_istart To $n_ub1 - 1
            For $j = $n_jstart To $n_ub2 - 1
                $s_toconsole &= "[" & $i & "][" & $j & "] = " & $a_arr[$i][$j] & @CRLF
            Next
            ConsoleWrite($s_toconsole)
            $s_toconsole = ""
        Next
        Return
    EndIf

    For $i = $n_istart To $n_ub1 - 1
        $s_toconsole &= "[" & $i & "] = " & $a_arr[$i] & @CRLF
    Next
    ConsoleWrite($s_toconsole)
EndFunc
1 person likes this

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Nice effort  :)
Anyhow this kind of analysis code needs some prerequisites and error checking to be done before using it

AutID

If parentheses are missing or untidy then the code should work anyway and apply operators precedence but with obviously a less accurate breakdown

Proper parentheses => accurate breakdown  :)

$eq = "(8 + (7 * 4)) - (3 - ((9 * 3) *(2 / (7 * 7))))"

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0