jess195 has asked for the
wisdom of the Perl Monks concerning the following question:

Hi all

I'm trying to build a calculator that would accept mathematical expressions from different users. I'm stuck in one part and would like to know good ways of solving the following problem:

I need to check what user enters against my answer. Say I have x + 1 as a correct answer, but user entered 1 + x. How can I build something that would check for all associativity and commutativity in a given equation? Of course that's one example but the problem gets more complicated when you have more than 4 variables. (with one unknown variable things are easy just easy)

I have used shunting yard algorithm to find the operators-precedence but it complicated things and I failed to do the task. Any idea how would I solve such a problem?

If you are trying to solve a permutation problem (which is what it sounds like to me), I think you are applying yourself incorrectly. Rather than figuring out how to map your answer to their answer, your parser should generate a canonical read that will necessarily map to yours. For your simple case, it might look like:

where a canonical sorting algorithm is used to order terms. Note that, if you want to accept complex expressions, the sort is non-trivial since you'll need to rank complex references, so cmp won't be enough. This type of format also supports nested operations:

Distributivity is something to think about... Thanks for bringing it up. And yes, I'm trying to solve a permutation problem taking commutativity and associativity properties into account. Looks to me this way is best that what I have been trying so far.... Thanks!

Long ago we did something similar in University studies (second year maybe) ... IIRC it was called minimal word (or term) problem.

In short you are transforming the term into a representation which allows a weighting function defining a maximum. The permutation (associativity, commutativity, ...) leading to the maximum is your normal form.

To terms leading to the same normal form are identical.

Sounds abstract but shouldn't be to difficult to achieve, e.g. normal forms of polynomials are easy, if you have different variables like in 5x³y² + 2xy²*, give certain variables a (e.g. lexicographic) precedence (i.e. x>y) and order them by exponent.

If your terms are not transformable to polynomials it gets a bit more difficult...

Substitute a semi-random range of numerical values for each variable into both equations and evaluate them. If the both result in the same answer, for a well-chosen set of inputs, they're probably the same equation.

Of course, that kind of just moves the goal posts a little to one of coming up with a good set of values; but given the performance of modern processors, unless these are quite complicated formulae, you can probably afford to throw a little (or even quite a lot) of everything at them and still get a statistically, highly probable answer in a few seconds.

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.

"Science is about questioning the status quo. Questioning authority".

In the absence of evidence, opinion is indistinguishable from prejudice.

actually I was using shunting yard algorithm to do me one thing: break down the equation into parts so I can swtich tings around. For example if I have a * b + c, then the algorithm should return: a b * c +, and then from here I would list different things, like add b a * c +, or c b a * + to the list of accepted equations, yet there are a lot to consider. But that's really difficult to do, as you will end up brute forcing everything. I believe the same goes to your way of solving it. I'm sure there is a smarter way to solve and take into consideration performance.

"I need to check what user enters against my answer. Say I have x + 1 as a correct answer, but user entered 1 + x. How can I build something that would check for all associativity and commutativity in a given equation?"

My thoughts on this was to substitute the variables with real values and then compare the results.
However, looking at some of your subsequent replies in this thread, I'm wondering if you really do want to compare two answers or generate a list of all possible answers:
assuming the former, here's some code I've been playing around with that you can possibly adapt to your needs.

As I had some fun with drawing binary trees recently, I thought, parsing equations into such a tree would be interesting as well. I was also able to simplify the tree for operations on numbers (in contrast to variables) and expand based on distributivity. But now I am stuck. I was thinking that some re-ordering would lead to a definite form for each equation but I have no idea how to go about it. In any case, the code produces the following output which might be of interest (or at least entertaining). (Numbers are written vertically, and I have used ^ instead of **.)