我有一个区分方程的函数,并将其作为列表打印到屏幕上。我现在要做的是一个函数,它接受像这样返回的表达式: '(+(* 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)
((+
))
))
答案 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)))
这只对表达式执行一次传递。通常,您希望执行过程直到结果不变。