Keith Code
Keith Code

Reputation: 57

Advice on how to tackle this lisp function.

I have written a function called my_rotate that takes a number from a user and creates a list up to five numbers. my_rotate then, pops off the first element of the list and adds it to the end of the list. Any advice on how I could write my_rotate to take in another number n and rotate the list based on the number n, in which the user entered.

Example:

> (my_rotate 1 2)

Outputs:

(3 4 5 1 2)

This is what I have so far:

(defun my_rotate (y)
    (append (loop for i from (+ 1 y) to (+ 4 y) collect i)
    (list y)))

Upvotes: 1

Views: 268

Answers (1)

sds
sds

Reputation: 60004

Here the function. I create two lists and then concatenate them.

(defun my-rotate (length shift)
  "Return a list of given LENGTH, rotated by SHIFT."
  (nconc
   (loop for i from (1+ shift) to (- length shift -2) collect i)
   (loop for i from 1 to shift collect i)))
(my-rotate 7 2)
==> (3 4 5 6 7 1 2)

Note that since both loops produce fresh lists, I use nconc instead of append.

If, however, you want to rotate an existing list, you will need to do something else:

(defun rotate-list (list shift)
  "Rotate the given LIST by the specified SHIFT."
  (let ((len (length list)))
    (setq shift (mod shift len)) ; handle circular shifts
    (append (nthcdr (- len shift) list)
            (butlast list shift))))
(rotate-list '(1 2 3 4 5 6) 2)
==> (5 6 1 2 3 4)
(rotate-list '(1 2 3 4 5 6) 20)
==> (5 6 1 2 3 4)               ; same because 20 = 2 mod 6
(rotate-list '(1 2 3 4 5 6) 0)
==> (1 2 3 4 5 6)               ; unchanged

Note that nthcdr points inside the original list, so we have to use append to avoid modifying the argument.

Note also that we scan the list argument twice (once in nthcdr and once in butlast). If your lists are huge, and profiling shows that this function is the bottleneck, you might want to re-write this using a loop (this is scenario is so unlikely, that I already regret having wasted my time writing this note).

Upvotes: 1

Related Questions