0

如何创建一个采用两个数字并准备从第一个数字到第二个数字的列表的方法。第一个数字总是正数并且小于第二个数字?我尝试了以下方法,但我不确定如何在 Scheme 中有一个全局变量来保存以前的值。

(define preplist  
  (let ((temp '())) 
   (lambda (x y) 
     (cond ((= x y) (append temp (list x)))
           (else (append temp (list x))
                 (display x)
                 (preplist (+ x 1) y))))))

预期结果是:(preplist 3 7) => (3 4 5 6 7)

有人可以帮忙解决这个问题吗?

4

2 回答 2

1

(x, y) 的解可以计算为:将 x 放在 (x+1, y) 的前面。因此它显然是递归的。像这样:

(define (preplist x y)
  (if (= x y)
      (list y)
      (cons x (preplist (+ x 1) y))))

看,它有效:

> (preplist 1 4)
(1 2 3 4)
> (preplist 5 7)
(5 6 7)
于 2013-03-19T06:32:35.213 回答
1

您的代码中有几个错误,对于初学者来说,您不需要在 a 中定义一个全局变量let来存储结果,在递归中推进时构建答案就足够了。并且不要append在这种情况下使用,如果密切遵循解决方案模板,acons就足以构建输出列表。

您应该坚持递归构建新列表的秘诀;这就是使用该配方解决问题的方法,它可能更像是这样的惯用语:

(define preplist
  (lambda (x y)
    (cond ((> x y)                          ; if the exit condition is met
           empty)                           ; then return the empty list
          (else                             ; otherwise
           (cons x                          ; cons the current element
                 (preplist (add1 x) y)))))) ; and advance the recursion

一种完全不同的方法是编写尾递归解决方案。这更有效,因为使用了恒定数量的堆栈。它不遵循上面概述的设计配方,但与您想到的解决方案有点相似 - 但请记住,这不使用全局变量(仅let用于迭代的命名)并且解决方案是累积的并作为参数传递:

(define (preplist x y)
  (let loop ((i y)             ; named let for iteration
             (acc empty))      ; define and initialize parameters
    (if (> x i)                ; if exit condition is met
        acc                    ; return accumulated value
        (loop (sub1 i)         ; otherwise advance recursion
              (cons i acc))))) ; and add to the accumulator

range当然,正如@dyoo 在评论中指出的那样,在实际设置中,您将使用与该过程基本相同的内置preplist过程。

于 2013-03-19T13:40:00.307 回答