L99 オレオレ解答 P16 から P20

どもです。
P16 から P20 です。無理に再帰で書こうとしているかなぁという感じもあったり,
loop を使っていこうと意気込んでいたころかなぁと。

;;;; P16
(defun drop (lst n)
  (labels ((drop-aux (l e)
             (cond ((null l) nil)
                   ((eq (car l) e) (drop-aux (cdr l) e))
                   (t (cons (car l) (drop-aux (cdr l) e))))))
  (drop-aux lst (nth (1- n) lst))))

(drop '(a b c d e f g h i j k) 3) => (A B D E F G H I J K)
(drop '(a b c d a b c c d e c) 3) => (A B D A B D E)
(drop '(a) 1) => NIL
(drop '(a a a) 3) => NIL

(defun drop (lst n)
  (loop for e1 in lst
       for e2 = (nth (1- n) lst)
       unless (eq e1 e2) collect e1))

(drop '(a b c d e f g h i j k) 3) => (A B D E F G H I J K)
(drop '(a b c d a b c c d e c) 3) => (A B D A B D E)
(drop '(a) 1) => NIL
(drop '(a a a) 3) => NIL

;;;; P17
(defun split (lst n)
  (cons (loop for i below n
             for e in lst
             collect e)
        (if (nthcdr n lst) (list (nthcdr n lst))
            nil)))

(split '(a b c d e f g h i j k) 3) => ((A B C) (D E F G H I J K))
(split '(a) 1) => ((A))
(split '(a b) 1) => ((A) (B))
(split '(a b) 2) => ((A B))

;;;; P18
(defun slice (lst i k)
  (loop for e in (nthcdr (1- i) lst)
       for n below (1+ (- k i))
       collect e))

(slice '(a b c d e f g h i k) 3 7) => (C D E F G)
(slice '(a b c) 1 3) => (A B C)
(slice '(a) 1 1) => (A)
(slice '() 1 1) => NIL

(defun slice (lst i k)
  (labels ((slice-aux (lst n)
             (if (or (null lst) (zerop n)) nil
                 (cons (car lst) (slice-aux (cdr lst) (1- n))))))
    (slice-aux (nthcdr (1- i) lst) (1+ (- k i)))))

(slice '(a b c d e f g h i k) 3 7) => (C D E F G)
(slice '(a b c) 1 3) => (A B C)
(slice '(a) 1 1) => (A)
(slice '() 1 1) => NIL

;;;; P19
(defun rotate (lst n)
  (if (or (zerop n) (null lst)) lst
      (let ((l (split lst (mod (+ (length lst) n) (length lst)))))
        (append (cadr l) (car l)))))

(rotate '(a b c d e f g h) 3) => (D E F G H A B C)
(rotate '(a b c d e f g h) -2) => (G H A B C D E F)
(rotate '(a b c d e f g h) 0) => (A B C D E F G H)
(rotate '() 5) => NIL

;;;; P20
(defun remove-at (lst n)
  (loop for i below (length lst)
       for e in lst
       unless (eq i (1- n))
       collect e))

(remove-at '(a b c d) 2) => (A C D)
(remove-at '(a) 1) => NIL
(remove-at '(a b) 2) => (A)

(defun remove-at (lst n)
  (labels ((remove-at-aux (l i)
             (cond ((null l) nil)
                   ((eq i n) (cdr l))
                   (t (cons (car l) (remove-at-aux (cdr l) (1+ i)))))))
    (remove-at-aux lst 1)))

(remove-at '(a b c d) 2) => (A C D)
(remove-at '(a) 1) => NIL
(remove-at '(a b) 2) => (A)