2013-04-07 72 views
3
(define rotate 
    (lambda (ls) 
      (define subrotate 
        (lambda (head tail res) 
          (if (null? tail) 
            res 
            (subrotate (append head (list (car tail))) 
               (cdr tail) 
               (cons (append tail head) res))))) 
      (if (null? ls) 
        ls 
        (subrotate '() ls '())))) (rotate '(a b c d e)) 

我想要的功能,如果列表(ABCDE),印刷((ABCDE)(BCDEA)(cdeab)(DEABC)(EABCD)),但是當我執行該功能,它打印(EABCD)(DEABC).......方案:旋轉功能無法正常工作

我覺得這個功能將激活像

尾|頭| | res

'()| (a b c d e)| '()

a | (b c d e)| (b c d e a)

(a b)| (c d e)| (c d e a b)

(a b c)| (d e)| (a b c)

(a b c d)| (e)| (e a b c d)

(a b c d e)| ()| (a b c d e)

我希望它只打印(a b c d e),但結果不是。我怎樣才能修改這個以及爲什麼它打印每一個旋轉?

回答

0

問題在於您將新元素添加到輸出列表的方式。這應該可以解決它:

(define rotate 
    (lambda (ls) 
    (define subrotate 
     (lambda (head tail res) 
     (if (null? tail) 
      res 
      (subrotate (append head (list (car tail))) 
         (cdr tail) 
         (append res (list (append tail head))))))) ; modified 
    (if (null? ls) 
     ls 
     (subrotate '() ls '())))) 

或者,你可以簡單地reverse輸出列表:

(define rotate 
    (lambda (ls) 
    (define subrotate 
     (lambda (head tail res) 
     (if (null? tail) 
      (reverse res) ; modified 
      (subrotate (append head (list (car tail))) 
         (cdr tail) 
         (cons (append tail head) res))))) 
    (if (null? ls) 
     ls 
     (subrotate '() ls '())))) 

而只是爲了好玩,這裏有一個更緊湊的實現相同的算法,這個時候使用了一個名爲let

(define (rotate ls) 
    (let subrotate ((head '()) (tail ls) (res '())) 
    (if (null? tail) 
     (reverse res) 
     (subrotate (append head (list (car tail))) 
        (cdr tail) 
        (cons (append tail head) res))))) 
+0

非常感謝,但我也想知道這個代碼如何打印每一個旋轉的列表。我認爲它應該只打印1個列表 – 2013-04-08 00:33:19

+0

帶有'(append tail head)'的部分創建每一個子列表,並且在遞歸的每次調用時,它們都會在'res'參數中累積 - 'res'作爲累加器爲輸出列表 – 2013-04-08 00:41:58

+1

謝謝。使用named let的實現也很有趣。 – 2013-04-08 00:54:49