2013-03-19 40 views
0

如何創建一個採用兩個數字並準備從第一個數字到第二個數字的列表的方法。第一個數字總是正數,小於第二個數字?我嘗試了以下,但我不知道如何在Scheme中擁有一個全局變量來保存以前的值。計算包含從x到y的數字的列表

(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)

可有一個請幫助解決這個問題?

+0

附註:這是一個在Racket中的內置程序:它被稱爲'range'。 http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Flist..rkt%29._range%29%29 – dyoo 2013-03-19 06:59:02

回答

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) 
+0

對不起,以前的評論是一個brainfart; p – leppie 2013-03-19 06:34:57

1

有在你的代碼幾次失誤,對於初學者來說,你不需要在let定義一個全局變量存儲結果,它的當你在遞歸中前進時足以構建答案。在這種情況下不要使用append,如果嚴格遵循解決方案模板,cons就足以構建輸出列表。

你應該堅持遞歸構建一個新列表的方法;這是怎樣的問題應該使用的配方來解決,這或許更多的慣用這樣的:

(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 

當然,在評論中指出的@dyoo,在實際內置range的過程,它確實基本相同preplist程序。

相關問題