使用Racket简化表达式

时间:2013-03-28 03:21:46

标签: scheme expression racket simplify

我有一个区分方程的函数,并将其作为列表打印到屏幕上。我现在要做的是一个函数,它接受像这样返回的表达式: '(+(* x 0)(* 2 1)) 并简化了答案。除去x * 0,因为它总是计算为零并用2替换2 * 1,最终只返回2,因为2 + 0是2。 这是我到目前为止所显示的内容,显然它非常缺乏,我们将非常感谢任何有关开始这项工作的帮助。

(define (simplify expr)
  (if (not (list? expr))
      expr
      (if (null? (cdr expr)) 
          (car expr)
          (case (car expr)
           ((+
               ))

       ))

2 个答案:

答案 0 :(得分:2)

这类问题的一般解决方案不是 简单。为了帮助您入门,请考虑使用重写规则,请查看文章A Hacker's Introduction to Partial Evaluation第4部分中显示的simplify过程:

We can use rewrite rules to simplify algebraic expressions. For example,

> (simplify '(+ (* 3 x) (* x 3)))
; (* 6 x)

This works by applying a list of rules to all parts of the subject expression
repeatedly until no more simplifications are possible:

(define *simplification-rules*
  '(((+ ?x ?x)          (* 2 ?x))
    ((* ?s ?n)          (* ?n ?s))
    ((* ?n (* ?m ?x))   (* (* ?n ?m) ?x))
    ((* ?x (* ?n ?y))   (* ?n (* ?x ?y)))
    ((* (* ?n ?x) ?y)   (* ?n (* ?x ?y)))))

The left hand column has patterns to match, while the right hand holds responses. 
The first rule says, if you see (+ foo foo), rewrite it into (* 2 foo). Variables 
like ?x can match anything, while ?m and ?n can only match numbers.

答案 1 :(得分:2)

假设你只是使用'*和'+作为运算符的二进制表达式,很容易编码代数的基本规则,并简化表达式的递归下降。如此:

(define (simplify exp)
 (cond ((number? exp) exp)
       ((symbol? exp) exp)
       ((list?   exp)
        (assert (= 3 (length exp)))
        (let ((operator  (list-ref exp 0))
              (operand-1 (simplify (list-ref exp 1)))   ; recurse
              (operand-2 (simplify (list-ref exp 2))))  ; recurse
          (case operator
            ((+)
             (cond ((and (number? operand-1) (= 0 operand-1)) operand-2)
                   ((and (number? operand-2) (= 0 operand-2)) operand-1)
                   ((and (number? operand-1) (number? operand-2)) 
                    (+ operand-1 operand-2))
                   (else `(,operator ,operand-1 ,operand-2))))

            ((*)
             (cond ((and (number? operand-1) (= 0 operand-1)) 0)
                   ((and (number? operand-2) (= 0 operand-2)) 0)
                   ((and (number? operand-1) (= 1 operand-1)) operand-2)
                   ((and (number? operand-2) (= 1 operand-2)) operand-1)
                   ((and (number? operand-1) (number? operand-2)) 
                    (* operand-1 operand-2))
                   (else `(,operator ,operand-1 ,operand-2))))
            (else 'unknown-operator))))
       (else 'unknown-expression)))

这只对表达式执行一次传递。通常,您希望执行过程直到结果不变。