Scheme 向左移动k次

Scheme 向左移动k次,scheme,racket,Scheme,Racket,嗨,我正在尝试在scheme中实现一个程序,将列表向左移动k次。 例如: (shift-k-left ’(1 2 3) 2) ’(3 1 2) 我成功地实现了一个代码,在这里左移一次: (define shift-left (lambda (ls) (if (null? ls) '() (append (cdr ls) (cons (car ls) '()))))) 我想在shift-k-left上使用shift

嗨,我正在尝试在scheme中实现一个程序,将列表向左移动k次。 例如:

(shift-k-left ’(1 2 3) 2)
’(3 1 2)
我成功地实现了一个代码,在这里左移一次:

(define shift-left
 (lambda (ls)
   (if (null? ls)
    '()
     (append (cdr ls)
          (cons (car ls)
                '())))))

我想在shift-k-left上使用shift left作为函数。

这里有一些类似的功能:

(define (addn value n)
  (let loop ((value value) (n n))
    (if (zero? n)
        value
        (loop (add1 value) (- n 1)))))

(addn 5 3)
; ==> 8
现在你可以做一个抽象:

(define (repeat proc)
  (lambda (v n)
    ...))
(define addn (repeat add1))

(addn 5 3)
; ==> 8

(define shift-k-left (repeat shift-left))
(shift-k-left ’(1 2 3) 2)
; ==> (3 1 2)
不用说,
repeat
看起来与
add1
非常相似

注:命名已关闭。您的实现更像是“旋转”而不是“移位”。
左移
实际上更像是
cdr
,而不是你的实现。

的想法是倒计时
n
,而
cons
r
汽车
倒推到
p
cdr
s倒推到
r
的后面。如果我们遇到一个
null?
r
我们
反转
p
并继续旋转:

(define (shift-k-left l n)
  ; assume that n >= 0
  (let loop ((n n) (p '()) (r l))   
    (if (= n 0)
        (append r (reverse p))
        (if (null? r)
            (loop n '() (reverse p))
            (loop (- n 1) (cons (car r) p) (cdr r))))))

下面是使用srfi/1中的循环列表的解决方案

  (require srfi/1)

  (define (shift xs k)
      (define n (length xs))
      (take (drop (apply circular-list xs) k) n))

使用
左移
来移动
k
次:

  • 如果
    k
    为0:不执行任何操作
  • 如果
    k
    不是0:shift
    k-1
    次,然后
    shift left
    结果
就是

(define (shift-left-k ls k)
    (if (= k 0)
        ls
        (shift-left (shift-left-k ls (- k 1)))))
您可能需要调整以对负
k
执行一些合理的操作