2017-02-19 7 views
1

Я написал функцию под названием my_rotate, которая берет число от пользователя и создает список из пяти чисел. my_rotate затем выталкивает первый элемент списка и добавляет его в конец списка. Любые советы о том, как я могу написать my_rotate, взять другой номер n и повернуть список на основе номера n, в который введен пользователь.Рекомендации о том, как решить эту функцию lisp.

Пример:

> (my_rotate 1 2)

Выходы:

(3 4 5 1 2)

Это то, что я до сих пор:

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

Что это такое? Могут быть лучшие способы достижения вашей общей цели. – blambert

ответ

1

Здесь функция. Я создаю два списка, а затем объединяю их.

(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) 

Обратите внимание, что поскольку оба loop s производят fresh списки, я использую nconc вместо append.

Если, однако, вы хотите, чтобы повернуть существующий список, вам нужно будет сделать что-то другое:

(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 

Обратите внимание, что nthcdr точки внутри исходного списка, так что мы должны использовать append, чтобы избежать модифицируя аргумент.

Заметим также, что мы сканируем list аргумент дважды (один раз в nthcdr и один раз в butlast). Если ваши списки огромны, а профилирование показывает, что эта функция является узким местом, вы можете переписать ее с помощью цикла (это сценарий настолько маловероятен, что я уже сожалею о том, что потерял время, написав эту заметку).

+0

Спасибо, я немного запутался в том, где в этой функции список фактически смещается. Не могли бы вы уточнить? –

+0

Какая функция? 1-й или 2-й? В обоих случаях я разбиваю исходный список в нужном месте, а затем объединяю детали. IOW, это функционально эквивалентно сдвигу, но выполняется за один раз. – sds

+0

Прошу прощения, я запутался в моей реализации функции, чтобы заставить меня думать, что что-то не так. Я вижу, какой цикл работает. Не могли бы вы сломать то, что каждый цикл выполняет в первой функции, чтобы я мог понять, что делает каждый цикл целиком. –

Смежные вопросы