【问题标题】:Simplify Expressions with Racket使用 Racket 简化表达式
【发布时间】:2013-03-28 03:21:45
【问题描述】:

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

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

       ))

【问题讨论】:

    标签: scheme expression racket simplify


    【解决方案1】:

    这类问题的一般解决方案并不那么那么简单。为了让您开始,请考虑使用重写规则,查看文章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.
    

    【讨论】:

    • 这取决于上下文。我从源头逐字引用,有时他们使用?s?n等作为变量名,而不是?x
    【解决方案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)))
    

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

    【讨论】:

      猜你喜欢
      • 2016-10-17
      • 1970-01-01
      • 2019-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      相关资源
      最近更新 更多