P14-P21: 細かい問題

だいたい同様の手順で解ける細かい問題。

pushして最後にreverse。

;; P14
(defun dupli (list)
  (let ((acc '()))
    (dolist (elm list)
      (dotimes (i 2)
      (push elm acc)))
    (reverse acc)))

(dupli '(a b c d e))
;; => (A A B B C C D D E E)
;; P15
(defun repli (list times)
  (let ((acc '()))
    (dolist (elm list)
      (dotimes (i times)
      (push elm acc)))
    (reverse acc)))

(repli '(a b c d e) 3)
;; => (A A A B B B C C C D D D E E E)
;; P16
(defun drop (list times)
  (let ((acc '())
	(i 0))
    (dolist (elem list)
      (if (= (incf i) times)
	  (setf i 0)
	  (push elem acc)))
    (reverse acc)))

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

P17ではcons cellが欲しかったのでdoをつかう。

;; P17
(defun split (list index)
  (do ((l list (cdr l))
       (acc '())
       (i 1 (1+ i)))
      ((> i index) (list (reverse acc) l))
    (push (car l) acc)))

(split '(1 2 3 4 5) 2)
;; => ((1 2) (3 4 5))
;; P18
(defun slice (list start end)
  (let ((acc '())
	(i 1))
    (dolist (elem list)
      (cond
       ((and (<= start i end)) (push elem acc))
       ((> i end) (return)))
      (incf i))
    (reverse acc)))

(slice '(a b c d e) 2 4)
;; => (B C D)
;; P19
(defun rotate (list n)
  (let* ((len (length list))
	 (split-point
	  (if (< 0 n)
	      (- len (mod (- n) len))
	      (mod n len))))
    (let ((split (split list split-point)))
      (append (second split)
	      (first split)))))

(rotate '(a b c d e f) 2)
;; => (C D E F A B)
(rotate '(a b c d e f) -2)
;; => (E F A B C D)
(rotate '(a b c d e f) 6)
;; => (A B C D E F) 
(rotate '(a b c d e f) -6)
;; => (A B C D E F) 

P20とP21は再帰で実装。
doでも出来たかな。

;; P20
(defun remove-at (list n)
  (if (<= n 1)
      (cdr list)
    (cons (car list)
	  (remove-at (cdr list) (1- n)))))

(remove-at '(a b c d e) 3)
;; => (A B D E) 

>|lisp|
;; P21
(defun insert-at (alt list n)
  (if (<= n 1)
      (cons alt (cdr list))
    (cons (car list)
	  (insert-at alt (cdr list) (1- n)))))

(insert-at 'alpha '(a b c d) 2)
;; => (A ALPHA B C)