Pattern Matching - Polynomial?

Hi all,

I’d like to try and use pattern matching to check - and ideally parse - a student’s answer that should be a polynomial of the form ax^3+bx^2+cx+d. However, I’m drawing a blank if I want to allow for some of the terms to be negative without a forced + - situation - for example, I would like 3x^3-2x^2+5x-3 to be ‘matched’ just the same as if b and d were positive, but pattern matching does not recognise this as a “sum”.

So far I’ve tried, where … is a pattern to match a polynomial term:

  • p.anyOf(p.sum(...), p.difference(...)) - works for matching (to a degree) but not parsing as you don’t seem to be able to parse an ‘anyOf’. Also I think I would need to exhaust every combination of addition and subtraction to account for all cases.
  • p.sum(p.repeat(p.anyOf(...,p.negative(...)))) - doesn’t recognise a negative coefficient as part of the “sum”. Also couldn’t parse because of ‘anyOf’.
  • p.contains(p.repeat(...)) - simply doesn’t match anything.

and a couple of other options that just failed with an error.

I can check the function evaluates to the correct answer, and with countNumberUsage I could probably enforce the simplified form by brute force - but it kind of seems like this is exactly what pattern matching is good for. I just can’t figure out, if it’s even possible, what the correct match would be.

Grateful for any thoughts. Thanks!

It’s not very efficient but (unless I’m unaware of something) you need to make multiple combinations using difference instead of sum.

I think much easier would be to just use function evaluation, and maybe eliminate a product pattern (if you’re looking to exclude an unexpanded form). There may also be a way to parse the number of terms.

p=patterns
expanded= not(p.product(p.expression, p.expression)

I think something like this, 2x(3x+4), may cause issues.

Thanks Daniel for your response. It’s reassuring to know I’m not missing something obvious (or we both are!).

Yes, useful to consider just ruling out the unexpanded version. My main thing I was trying to eliminate was repeated like terms - students entering 5x^3+…+3x^3+… rather than the simplified form.

I made some progress by just looking for p.contains and matching terms that way. Will need to add some optionality into the mix but essentially

p3=p.product(p.integer,p.exponent(p.literal(`x`),p.integer.satisfies(`x=3`)))
p2=p.product(p.integer,p.exponent(p.literal(`x`),p.integer.satisfies(`x=2`)))
p1=p.product(p.integer,p.literal(`x`))
p0=p.integer

then

tru=p.contains(p3).matches(this.latex) and p.contains(p2).matches(this.latex) and ...

which works fine. I can also parse out the (absolute) coefficients using the not-exactly-intuitive

val2=p2.parse(p.contains(p2).parse(this.latex).term1.latex).term1.numericValue

Maybe there’s a way of tidying that up that I’m not spotting!

I looked at an example @Jay provided for p.repeat and thought that maybe I could be clever and use something like

nump2=p.contains(p.repeat(p2)).parse(this.latex).term1.n 

to identify how many occurences there are of p2 (bx^2) and reject if it’s >1. However, including this seems to break the pattern matching for some reason - an expression that marks as true when I don’t have that parsing in place, marks as false when I do. I don’t know if this is a bug or intended or I’ve misunderstood that particular pattern.

For now, though, I think we have a semi-solution.