如何基于已实现的单次左移函数完成Scheme列表k次左移?
shift-k-left by Reusing shift-left in Scheme First, let's confirm your existing shift-left function works perfectly for single shifts—it correctly moves the first element to the end of the list:
(define shift-left (lambda (ls) (if (null? ls) '() (append (cdr ls) (cons (car ls) '())))))
To extend this to shifting left k times, we just need to repeat this operation k times. Let's look at a few robust implementations:
Recursive Version (Simple & Intuitive)
This recursive approach calls shift-left once per iteration, decrementing k until it reaches 0:
(define shift-k-left (lambda (ls k) (cond ((null? ls) '()) ; Handle empty list ((zero? k) ls) ; Base case: no shifts needed (else (shift-k-left (shift-left ls) (- k 1)))))) ; Recurse with shifted list and k-1
Testing your example:
(shift-k-left '(1 2 3) 2) ; Returns '(3 1 2)
Optimized Recursive Version (Handles Large k)
If k is larger than the length of the list, shifting k times is the same as shifting k mod length(ls) times. This optimization avoids redundant shifts:
(define shift-k-left (lambda (ls k) (let ((len (length ls))) (cond ((or (null? ls) (zero? len)) '()) ; Edge case: empty list (else (let ((effective-k (modulo k len))) (if (zero? effective-k) ls ; k is a multiple of length, no shift needed (shift-k-left (shift-left ls) (- effective-k 1)))))))))
For example, (shift-k-left '(1 2 3) 5) will compute 5 mod 3 = 2, then shift twice—same result as shifting 2 times directly.
Iterative Version (Tail-Call Optimized)
If you prefer an iterative approach (which is tail-recursive in Scheme, so no stack overflow risk), you can use a do loop:
(define shift-k-left (lambda (ls k) (let ((len (length ls))) (cond ((or (null? ls) (zero? len)) '()) (else (let ((effective-k (modulo k len))) (do ((i 0 (+ i 1)) (current-ls ls (shift-left current-ls))) ((= i effective-k) current-ls))))))))
All these implementations reuse your existing shift-left function exactly as you wanted, and handle edge cases like empty lists or large values of k gracefully.
内容的提问来源于stack exchange,提问作者נירייב שמואל

