2017-02-19 4 views
1

my_rotate이라는 함수를 작성하여 사용자로부터 숫자를 받고 5 개의 숫자까지 목록을 만듭니다. my_rotate 그러면 목록의 첫 번째 요소가 튀어 나와 목록의 끝에 추가됩니다. my_rotate에 다른 숫자 n을 입력하고 사용자가 입력 한 숫자 n을 기반으로 목록을 회전시킬 수있는 방법에 대한 조언.이 lisp 기능을 다루는 방법에 대한 조언.

예 :

> (my_rotate 1 2)

출력 : 여기

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

어쨌든이게 뭐야? 전반적인 목표를 달성하는 더 좋은 방법이있을 수 있습니다. – blambert

답변

1

기능 :

(3 4 5 1 2)

이것은 내가 지금까지 가지고있는 것입니다. 두 개의 목록을 만든 다음 연결합니다. 모두 loopfresh 목록을 생성하기 때문에, 내가 대신 appendnconc를 사용하는 것이

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

참고. 원래 목록 내부 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, 이것은 기능적으로 shift와 동일하지만 한 번에 수행됩니다. – sds

+0

죄송합니다. 기능 구현에 혼란스러워서 뭔가 잘못되었다고 생각하게되었습니다. 어떤 루프가 무엇을하는지 보았습니다. 첫 번째 함수에서 각 루프가 수행하는 작업을 분석하여 각 루프가 전체적으로 무엇을하는지 이해할 수 있습니다. –

관련 문제