2017-02-19 44 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我國農產品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以避免修改論據。

還要注意的是,我們(在butlastnthcdr各一次)掃描list參數兩次。 如果你的列表很大,並且分析表明這個函數是瓶頸,那麼你可能需要用循環重寫這個(這種情況是不太可能的,我已經很浪費時間寫這篇文章了)。

+0

謝謝,我對這個函數中的列表實際移位的地方有點困惑。你能澄清嗎? –

+0

哪個功能?第一還是第二?在這兩種情況下,我都將原始列表分割到正確的位置,然後合併這些部分。 IOW,這在功能上等同於換檔,但是一次完成。 – sds

+0

對不起,我對函數的實現感到困惑,讓我覺得有什麼錯誤。我確實看到哪個循環在做什麼。你能否分解每個循環在第一個函數中所做的事情,以便我能夠理解每個循環完全在做什麼。 –

相關問題