Lisp格式多项式

Lisp格式多项式,lisp,common-lisp,Lisp,Common Lisp,我将稀疏多项式表示为(系数,对)列表。例如: '((1 2) (3 6) (-20 48)) => x^2 + 3x^6 - 20x^48 我不熟悉Lisp格式,但是遇到了一些非常漂亮的工具,比如(format nil“~:[+~;-~]”(>0系数))以文本形式获取系数的符号(我知道,这可能不是惯用法) 但是,格式化单个术语时会出现某些显示问题。例如,以下各项均应为真: (1 0) => 1x^0 => 1 (reducible) (1 1) => 1x^1 =

我将稀疏多项式表示为(系数,对)列表。例如:

'((1 2) (3 6) (-20 48)) => x^2 + 3x^6 - 20x^48
我不熟悉Lisp格式,但是遇到了一些非常漂亮的工具,比如
(format nil“~:[+~;-~]”(>0系数))
以文本形式获取系数的符号(我知道,这可能不是惯用法)

但是,格式化单个术语时会出现某些显示问题。例如,以下各项均应为真:

(1 0) => 1x^0 => 1    (reducible)
(1 1) => 1x^1 => x    (reducible)
(1 2) => 1x^2 => x^2  (reducible)
(2 0) => 2x^0 => 2    (reducible)
(2 1) => 2x^1 => 2x   (reducable)
(2 2) => 2x^2 => 2x^2 (this one is okay)
我想知道是否有一种方法可以在不使用大量
if
cond
宏的情况下实现这一点-一种只使用单个
格式
模式的方法。除了“美化”术语(FormatPolynomialHelper3中的最后一行应该可以做到这一点)之外,一切都正常

编辑:正确地说输出不应该包含逻辑。也许我问的问题太具体了。下面是正确格式化多项式的逻辑-但我正在寻找更干净、更可读、更具lisp风格的东西(这只是我编写lisp的第三天)


回答

(defun term-m (term)
  (first term))

(defun term-e (term)
  (second term))

(defun simplify-polynomial (p)
  (remove-if #'zerop (sort p #'> :key #'term-e)
             :key #'term-m))

(defun write-term (m e start-p stream)
  ; sign or operator
  (cond ((and (minusp m) start-p)
         (princ "-" stream))
        ((not start-p)
         (princ (if (plusp m) " + " " - ") stream)))
  ; m
  (cond ((not (= (abs m) 1))
         (princ (abs m) stream)))
  (princ "x" stream)
  ; e
  (cond ((not (= 1 e))
         (princ "^" stream)
         (princ e stream))))

(defun write-polynomial (p &optional (stream *standard-output*))
  (loop for (m e) in (simplify-polynomial p)
        for start-p = t then nil
        do (write-term m e start-p stream)))
CL-USER 14 > (write-polynomial '((1 2) (3 6) (-20 48)))
-20x^48 + 3x^6 + x^2
我不会将此逻辑放入
格式
语句中。仅当您希望加密代码或为自己创建更多维护工作时。好的Lisp代码是自文档的<代码>格式语句从不自我记录

在打印之前,我首先简化多项式。例如,删除每个乘以零的项

((0 10) (1 2)) -> ((1 2))
然后,如果乘数为1,则可以在正常的
条件下
情况下
语句中进行测试

另外,请确保不要使用带有自制数据结构的
汽车
CDR
第一个
第二个
。多项式的组件应该主要通过隐藏大部分实现细节的自文档化函数来访问

我将不使用
格式编写它

示例代码

(defun term-m (term)
  (first term))

(defun term-e (term)
  (second term))

(defun simplify-polynomial (p)
  (remove-if #'zerop (sort p #'> :key #'term-e)
             :key #'term-m))

(defun write-term (m e start-p stream)
  ; sign or operator
  (cond ((and (minusp m) start-p)
         (princ "-" stream))
        ((not start-p)
         (princ (if (plusp m) " + " " - ") stream)))
  ; m
  (cond ((not (= (abs m) 1))
         (princ (abs m) stream)))
  (princ "x" stream)
  ; e
  (cond ((not (= 1 e))
         (princ "^" stream)
         (princ e stream))))

(defun write-polynomial (p &optional (stream *standard-output*))
  (loop for (m e) in (simplify-polynomial p)
        for start-p = t then nil
        do (write-term m e start-p stream)))
CL-USER 14 > (write-polynomial '((1 2) (3 6) (-20 48)))
-20x^48 + 3x^6 + x^2
示例使用

(defun term-m (term)
  (first term))

(defun term-e (term)
  (second term))

(defun simplify-polynomial (p)
  (remove-if #'zerop (sort p #'> :key #'term-e)
             :key #'term-m))

(defun write-term (m e start-p stream)
  ; sign or operator
  (cond ((and (minusp m) start-p)
         (princ "-" stream))
        ((not start-p)
         (princ (if (plusp m) " + " " - ") stream)))
  ; m
  (cond ((not (= (abs m) 1))
         (princ (abs m) stream)))
  (princ "x" stream)
  ; e
  (cond ((not (= 1 e))
         (princ "^" stream)
         (princ e stream))))

(defun write-polynomial (p &optional (stream *standard-output*))
  (loop for (m e) in (simplify-polynomial p)
        for start-p = t then nil
        do (write-term m e start-p stream)))
CL-USER 14 > (write-polynomial '((1 2) (3 6) (-20 48)))
-20x^48 + 3x^6 + x^2
术语
'(10)
'(20)
的格式分别为
x^0
2x^0
,它们应该是
1
2