2013-04-07 41 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