方案更换问题

时间:2013-02-26 18:41:38

标签: scheme racket

此代码将第一人称单词替换为第二人称单词,反之亦然。但是,对于短语中的每个单词,它会遍历每一对,因此有时它会改变回来。

以下是代码:

(define (replace pattern replacement lst replacement-pairs)
  (cond ((null? lst) '())
    ((equal? (car lst) pattern)
       (cons replacement
             (many-replace (cdr replacement-pairs) (cdr lst))))
    (else (cons (car lst)
          (many-replace (cdr replacement-pairs) (cdr lst))))))

(define (many-replace replacement-pairs lst)
  (cond ((null? replacement-pairs) lst)
     (else (let ((pat-rep (car replacement-pairs)))
        (replace (car pat-rep)
                 (cadr pat-rep)
                 (many-replace (cdr replacement-pairs)
                 lst) replacement-pairs)))))

(define (change-person phrase)
  (many-replace '((i you) (me you) (am are) (my your) (are am) (you i) (your my))
            phrase))

例如,如果我输入

(change-person '(you are not being very helpful to me))

它会改变你,然后再回到你身边。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

程序replacemany-replace过于复杂,相互递归并没有按照您的想法进行。如果我们简化这些过程并确保在输入列表上只执行一次传递,我们可以得到正确的答案:

(define (replace replacement-pairs pattern)
  (cond ((null? replacement-pairs)
         pattern)
        ((equal? (caar replacement-pairs) pattern)
         (cadar replacement-pairs))
        (else
         (replace (cdr replacement-pairs) pattern))))

(define (many-replace replacement-pairs lst)
  (if (null? lst)
      '()
      (cons (replace replacement-pairs (car lst))
            (many-replace replacement-pairs (cdr lst)))))

敏锐的眼光会注意到以前的程序可以通过使用一些高阶程序以简洁的方式表达。一个更惯用的解决方案可能如下所示:

(define (replace replacement-pairs pattern)
  (cond ((assoc pattern replacement-pairs) => cadr)
        (else pattern)))

(define (many-replace replacement-pairs lst)
  (map (curry replace replacement-pairs) lst))

无论哪种方式,它都按预期工作:

(change-person '(you are not being very helpful to me))
=> '(i am not being very helpful to you)

答案 1 :(得分:0)

我写了一个稍微简单的解决方案:

(define (many-replace pattern phrase)
  (let loop ((phrase phrase) (result '()))
    (if (empty? phrase) (reverse result)
        (let* ((c (car phrase)) (a (assoc c pattern)))
          (if a
              (loop (cdr phrase) (cons (cadr a) result))
              (loop (cdr phrase) (cons c result)))))))

(change-person '(you are not being very helpful to me))
=> '(i am not being very helpful to you)