ANSI Common Lisp 3章 「リスト」
チマチマと練習問題をやってみた.
2. もとのリストでの要素の並びを保持するように動作するunion
(defun new-union (lst oth) (if (null lst) oth (funcall #'(lambda () (dolist (elt lst) (setf oth (remove elt oth))) (append lst oth))))) > (union '(a b c) '(b a d)) (C B A D) > (new-union '(a b c) '(b a d)) (A B C D)
きもい.lambdaの中がきもい.なんか手続きっぽい.
3. 1つのリストを引数として,各々の要素が出現する回数を返す関数
ちなみに,出現する回数でsortしなければならない.
(defun occurrences (lst) (sort (counter '() lst) #'> :key #'cdr)) (defun counter (alist lst) (if (null lst) alist (let ((elt (car lst))) (counter (append-alist alist (count elt lst) elt) (remove elt lst))))) (defun append-alist (alist num elt) (append alist (list (cons elt num) ))) > (occurrences '(a b c d a a c c c d b)) ((C . 4) (A . 3) (B . 2) (D . 2)) > (occurrences '(a b c d a a c c c d b d a a)) ((A . 5) (C . 4) (D . 3) (B . 2))
最後のsortする部分がどうもわかんなかったので,P.Graham 著 ANSI Common LISP 練習問題解答を参考にした.しかもeqlで比較しなければいけないようだけれど,countしてremoveのほうが楽そうだったのでこんなアプローチ.
5. 各々の要素にその位置を示す数を加えて返す
再帰,反復,mapcarを用いて示す.
;; recursive (defun pos+a (lst) (inner-a 0 lst)) (defun inner-a (pos lst) (if (null lst) nil (cons (+ (car lst) pos) (inner-a (+ pos 1) (cdr lst))))) ;; loop (defun pos+b (lst) (do ((pos 0 (+ pos 1))) ((null (nth pos lst)) lst) (setf (nth pos lst) (+ (nth pos lst) pos)))) ;; mapcar (defun pos+c (lst) (let ((i -1)) (mapcar #'(lambda (x) (+ x (setf i (+ i 1)))) lst))) > (pos+a '(7 5 1 4)) (7 6 3 7) > (pos+b '(7 5 1 4)) (7 6 3 7) > (pos+c '(7 5 1 4)) (7 6 3 7)
mapcar版の,lambdaでsetfしてる辺りがえぐいなぁとか思いながらも,参考にしてる解答ではincfマクロを使用しているので,しょうがない感が否めない.rubyなら,mapcar版はこんな感じになるのか.
i = -1 [7, 5, 1, 4].map {|e| e + ( i += 1)} => [7, 6, 3, 7]
今日はこれぐらいで.