2017-02-19 2 views
1

私はmy_rotateという関数を書いています。この関数は、ユーザーから数値を受け取り、最大5つの数値のリストを作成します。 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

機能。 2つのリストを作成して連結します。

(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リストを生成するので、私が代わりにappendnconcを使用することに注意してください。元のリスト内のnthcdrポイントは、私たちは変更を避けるために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 

注:ただし、既存のリストを回転させたい場合は

、あなたが何かを行う必要があります引数。我々は(butlastに一度nthcdrで、一度)二回list引数をスキャンすることも

注意。 リストが巨大でプロファイリングでこの機能がボトルネックであることがわかっている場合は、ループを使用してこの機能を書き直したいと思うかもしれません(このシナリオはあまりありません。

+0

ありがとう、私は少しこの機能では、リストが実際にシフトされている上で混乱しています。明確にできますか? –

+0

どちらが機能しますか? 1位か2位?どちらの場合も、元のリストを適切な場所に分割してから部分をマージします。 IOW、これは機能的にはシフトと同じですが、一度に実行されます。 – sds

+0

申し訳ありませんが、何かが間違っていると思うように機能の実装に混乱しました。どのループが何をしているのか分かります。最初の関数で各ループが何をしているのか分かり、各ループが何をしているのかを理解できます。 –