A simple polynomial calculator in lisp

poly.cl 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. ;; Add two polynomials together
  2. (defun poly+ (poly1 poly2)
  3. (add-terms (append poly1 poly2)))
  4. ;; Subtract one polynomial from another
  5. (defun poly- (poly1 poly2)
  6. (add-terms (append poly1 (flip-multipliers poly2))))
  7. ;; Multiply polynomials together
  8. (defun poly* (poly1 poly2)
  9. (clear-zero (add-terms (multiply-terms poly1 poly2))))
  10. ;; Returns the variable component of a singular polynomial
  11. (defun variable-symbol (single-poly)
  12. (car (car single-poly)))
  13. ;; Returns the exponent component of a singular polynomial
  14. (defun exponent (single-poly)
  15. (car (cdr (car single-poly))))
  16. ;; Returns the multiplier component of a singular polynomial
  17. (defun multiplier (single-poly)
  18. (car (cdr single-poly)))
  19. ;; Returns a polynomial with all the multipliers multiplied by -1
  20. (defun flip-multipliers (poly)
  21. (map 'list #'(lambda (x)
  22. (list (list (variable-symbol x) (exponent x))
  23. (* (multiplier x) -1))) poly))
  24. ;; Returns an added term if the addition is succesful, nil otherwise
  25. (defun term-addition (term1 term2)
  26. (if (and (equal (variable-symbol term1) (variable-symbol term2))
  27. (equal (exponent term1) (exponent term2)))
  28. (list (list (variable-symbol term1) (exponent term1))
  29. (+ (multiplier term1) (multiplier term2)))
  30. nil))
  31. ;; Returns the failed term if the addition fails, nil otherwise
  32. (defun term-failure (term1 term2)
  33. (if (and (equal (variable-symbol term1) (variable-symbol term2))
  34. (equal (exponent term1) (exponent term2)))
  35. nil
  36. term2))
  37. ;; Returns true if a polynomial contains only unique terms
  38. (defun poly-unique-terms? (poly)
  39. (cond ((equal poly nil) T)
  40. (T (if (some #'(lambda (x) (and (equal (flatten
  41. (variable-symbol x))
  42. (flatten
  43. (variable-symbol
  44. (car poly))))
  45. (equal (flatten (exponent x))
  46. (flatten (exponent (car poly))))))
  47. (cdr poly))
  48. nil
  49. (poly-unique-terms? (cdr poly))))))
  50. ;; Functional flatten from Rosetta Code:
  51. ;; http://rosettacode.org/wiki/Flatten_a_list#Common_Lisp
  52. (defun flatten (x &optional stack out)
  53. (cond ((consp x) (flatten (rest x) (cons (first x) stack) out))
  54. (x (flatten (first stack) (rest stack) (cons x out)))
  55. (stack (flatten (first stack) (rest stack) out))
  56. (t out)))
  57. ;; This function replaces a full list of nils with the replace-term, otherwise
  58. ;; returns the list
  59. (defun useful-replace-nil (addition-seq replace-term)
  60. (if (equal (remove nil addition-seq) nil)
  61. (list replace-term)
  62. addition-seq))
  63. ;; Removes all zeroes from the polynomial
  64. (defun clear-zero (poly)
  65. (remove nil (map 'list #'(lambda (x)
  66. (if (or (equal (multiplier x) 0) (equal (exponent x) 0)) nil x))
  67. poly)))
  68. ;; Recursively adds all the terms in the list
  69. (defun add-terms (poly)
  70. (cond
  71. ((poly-unique-terms? poly) (clear-zero poly))
  72. (T (add-terms (remove nil (append (map 'list #'(lambda (x)
  73. (term-failure (car poly) x))
  74. (cdr poly))
  75. (useful-replace-nil (map 'list #'(lambda (y)
  76. (term-addition (car poly) y))
  77. (cdr poly)) (car poly))))))))
  78. (defun map-onto-poly (single-poly poly)
  79. (map 'list #'(lambda (x) (multiply-singles single-poly x)) poly))
  80. (defun multiply-singles (single-poly1 single-poly2)
  81. (cond
  82. ((equal (variable-symbol single-poly1) (variable-symbol single-poly2))
  83. (list (list (variable-symbol single-poly1)
  84. (if (typep (exponent single-poly1) 'list)
  85. (map 'list #'+ (exponent single-poly1)
  86. (exponent single-poly2))
  87. (+ (exponent single-poly1) (exponent single-poly2))))
  88. (* (multiplier single-poly1) (multiplier single-poly2)))
  89. )
  90. (T
  91. (list (list (list (variable-symbol single-poly1)
  92. (variable-symbol single-poly2))
  93. (list (exponent single-poly1)
  94. (exponent single-poly2)))
  95. (* (multiplier single-poly1) (multiplier single-poly2))))))
  96. (defun multiply-terms (map-poly poly)
  97. (cond
  98. ((equal map-poly nil) nil)
  99. (T (remove nil (append (map-onto-poly (car map-poly) poly)
  100. (multiply-terms (cdr map-poly) poly))))))
  101. ; (poly+ '(((x 2) 3)) '(((y 2) 4)))
  102. ; (poly+ '(((x 2) 3) ((y 2) 3)) '(((y 2) 4)))