关于如何解决这个lisp函数的建议。

时间:2017-02-19 23:06:01

标签: list lisp common-lisp clisp

我编写了一个名为my_rotate的函数,它从用户那里获取一个数字并创建一个最多五个数字的列表。然后,my_rotate弹出列表的第一个元素并将其添加到列表的末尾。关于我如何写my_rotate以接收另一个号码n并根据用户输入的号码n轮换列表的任何建议。

示例:

> (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 个答案:

答案 0 :(得分: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生成了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)。 如果您的列表很大,并且分析显示此函数是瓶颈,您可能想要使用循环重写(这种情况是不太可能的,我已经后悔浪费了我写这篇文章的时间)。