-1

I'm writing writing polynomial arithmetic in lisp, and currently working on addition. I need help sorting a polynomial by the exponent and symbol. My polynomials are represented as follows:

((3 ((1 x)(1 y))) (1 ((3 y)))) ; == 3xy + 1y^3

The function I need guidance with is given a term like

((5 ((3 x))) (3 ((3 y))) (4 ((2 z)))) ((6 ((3 x))) (1 ((3 y))) (9 ((2 z)))))

I would want:

((4 ((2 Z))) (9 ((2 Z))) (5 ((3 X))) (6 ((3 X))) (3 ((3 Y))) (1 ((3 Y))))

returned, so that all So all z^2 and z^2 are together.

Josh Horton
  • 77
  • 1
  • 1
  • 7
  • You mention in one place `((3((1x)(1y)))`, which has a number and two symbols, but then later things like `(9 ((2 Z)))`, which have two numbers and a symbol. Should we assume that the first is a typo? – Joshua Taylor Dec 02 '15 at 13:03
  • Not that's it's useful, but is this any connection to the problem mentioned in [this question](http://stackoverflow.com/q/34010101/1281433)? – Joshua Taylor Dec 02 '15 at 13:03
  • By itself, `((5((3 x)))(3((3 y)))(4((2 z))))((6((3 x)))(1((3 y)))(9((2 z)))))` doesn't make sense; the parenthesis aren't balanced. There are supposed to be two polynomials that you're adding together, right? – Joshua Taylor Dec 02 '15 at 13:08
  • No own effort shown. :-( – Rainer Joswig Dec 02 '15 at 13:42

2 Answers2

1

Your initial example shows terms with two variables (e.g., 3xy), but your example later on doesn't. This solution won't handle the multiple variable term case (and you haven't said how you'd want grouping in that case anyhow), but it will handle your example.

First, define some abstractions for working with your polynomial terms, because they're rather inconvenient at the moment. Here are three functions that make it much easier to extract the coefficient, degree, and variable from each term:

(defun polynomial-term-coefficient (term)
  (destructuring-bind (coefficient ((degree variable))) term
    (declare (ignore degree variable))
    coefficient))

(defun polynomial-term-degree (term)
  (destructuring-bind (coefficient ((degree variable))) term
    (declare (ignore coefficient variable))
    degree))

(defun polynomial-term-variable (term)
  (destructuring-bind (coefficient ((degree variable))) term
    (declare (ignore coefficient degree))
    variable))

Then, as I understand your question, you're actually starting with two polynomials 5x3 + 3y3 + 4z2 and 6x3 + y3 + 9z2. You'd add those together first, just by appending the list of their terms. Then you can sort that on the predicate string> (which takes string designators, so symbols are OK), with a key function of polynomial-term-variable. That is, you use the key function to extract the value that you actually want to sort by.

(let ((p1 '((5 ((3 x))) (3 ((3 y))) (4 ((2 z)))))
      (p2 '((6 ((3 x))) (1 ((3 y))) (9 ((2 z))))))
  (let ((unsimplified-sum (append p1 p2)))
    (sort (copy-list unsimplified-sum) 'string> :key 'polynomial-term-variable)))
;=> ((4 ((2 Z))) (9 ((2 Z))) (3 ((3 Y))) (1 ((3 Y))) (5 ((3 X))) (6 ((3 X))))
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Yes they do start as two polynomials that are appended together. The explanation you have given is great thanks. The idea of the program is to have addition, subtraction and multiplication functions. Addition is now working. For subtraction I was thinking of writing a function that would negate a polynomial then use the addition function. Does this sound right? Any guidance you could give me to starting the multiplication function would be really appreciated. – Josh Horton Dec 02 '15 at 16:31
  • Also, the sort function here sorts by the variable. Is it possible to sort by both variable and degree? So 2^x will always be next to other 2^x. so it sorts first by the variable x then by the degree 2? – Josh Horton Dec 02 '15 at 16:50
  • Sure, just use a predicate other than string>,that knows how to compare by variable, then degree. – Joshua Taylor Dec 02 '15 at 16:53
  • If you look at the edit in the question I have tried to set up a predicate so it will sort by both. Is this the right sort of thing? Cant find any documentation to support sorting by two elements in common lisp. – Josh Horton Dec 02 '15 at 18:35
  • @JoshHorton I think that's really a different question, and it doesn't appear that you really put much effort in trying to find a solution either. Why would a function A function like `(define foo (x y) (p x y) (q x y))` is always going to return `(q x y)`. I don't see why you'd suppose that your predicate is comparing two attributes of the input. – Joshua Taylor Dec 02 '15 at 18:44
  • I have edited the question to show a solution I have come up with that I do believe works. It's a bit messy though and I don't use the abstraction that you showed. Do you think this is a good way to sort? Is there other better/simpler ways to do this? I apologies for my last question. I see now it was rushed and not well thought through. – Josh Horton Dec 02 '15 at 23:17
0

You might want to have a search for "Horner's method", which is an old numerical method for computing the value of a polynomial in O(n) time, n being the number of terms. It looks from the outset that's close to what you want to do, or at least similar in representation.

scooter me fecit
  • 1,053
  • 5
  • 15