您的位置:首页 > 其它

P19 (**) Rotate a list N places to the left.

2016-01-18 21:21 197 查看

问题描述

sash> (rotate '(a b c d e f g h) 3)
-> ((a b c) (d e f g h i k))
sash> (rotate '(a b c d e f g h) -2)
-> (g h a b c d e f)


Hint: Use the predefined functions
length
and
append
, as well as the result of problem P17.

解法

普通实现

按照题目的提示,很直观得到:

(define rotate
(lambda (ls N)
(cond
[(zero? N) ls]
[else
(let* ([n (if (positive? N)
N
(+ (length ls) N))]
[s (split ls n)])
(append (cadr s) (car s)))])))


使用到了
length
append
,以及P17定义的
split


CPS实现

(define split-2
(lambda (ls n k)
(let f ([i 1]
[s ls]
[k k])
(cond
[(null? s) (k '() '())]
[(<= i n) (f (+ i 1) (cdr s)
(lambda (ls1 ls2)
(k (cons (car s) ls1)
ls2)))]
[else (f (+ i 1) (cdr s)
(lambda (ls1 ls2)
(k ls1 (cons (car s) ls2))))]))))
(define return
(lambda (ls1 ls2)
(append ls2 ls1)))

(define rotate
(lambda (ls N)
(cond
[(zero? N) ls]
[else
(let ([n (if (positive? N)
N
(+ (length ls) N))])
(split-2 ls n return))])))


split-2
的功能仍然是分割的两个列表,这个定义没有改变。这里改变了
return
的定义,用来组装
split-2
得到的两个列表,P17要求返回这两个列表作为元素的列表,而该题目则要求按规则
append
成一个列表。
rotate
则包含了顶层逻辑,处理
N
的各种情况对应的结果逻辑。

其他方式

看到另外一种解法:

(define (rotate xs n)
(if (< n 0)
(reverse (rotate (reverse xs) (- n)))
(let ((parts (split xs n)))
(append (cadr parts) (car parts)))))


看似简洁,但有逻辑冗余:当
n
为负时,会用
-n
作为
rot
4000
ate
的参数,这时仍然要判断
if
语句,实际上我们已经知道了
-n
为正。

不建议将对
n
的处理放入递归逻辑中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lisp scheme 算法