L99 オレオレ解答 P06 から P10編

どもです。
中掃除くらいの規模の掃除をして,筋肉痛もあいまみあって大変疲れたとです。
L99 を少々解いてから,land of list を続きから読んだら,
なんか以前よりも解るようになった気がする。
やはり習うより慣れろの如く,練習して慣れるというのが大事なんだと実感。
あと,一度問題を解いたら,時間をおいてから解答を見直して,
もっとシンプルな方法がないかと考えるのが大事だと,
P26 の組み合わせを求める問題を解いてみて実感。


がっ,以下の解答については,再考していないという矛盾。
compress とか pack とかについては,スマートな方法がありそう。
というか,L99 の解答ってあるんだろうか。
それから,ユニットテスト的なものを入れようと思って,
cl-test-more というのが,これのみで使えるとかあったので使おうとしたが,
なんかが足りないと怒られた。なので諦めた。
たぶんライブラリ的なものがないんでしょう。
Cygwin 入れたときに入っていた clisp を使っているので,たぶん素の状態なんだろうと。
その辺の仕組み,よくわかったないっす。
あと,slime っていうのはよくできてるなぁ。感謝ですね。
Hyperspec っていうドキュメントを,C-c C-d h ですぐ引けるのが大変うれしい。
これについてもありがとうですね。


というわけで,オレオレ解答。この辺はまだ順調だけど,ぼちぼちペースが落ちてきている。。。

P06 から P10
;;;; P06
(defun palindrome-p (lst)
  (labels ((rev-aux (lst ret)
             (if (null lst)
                 ret
                 (rev-aux (cdr lst) (cons (car lst) ret))))
           (rev (lst)
             (rev-aux lst nil)))
    (equal lst (rev lst))))

(palindrome-p '(x a m a x)) => T
(palindrome-p '()) => T
(palindrome-p '(a)) => T
(palindrome-p '(a b b a)) => T

;;;; P07
(defun my-flatten (lst)
  (cond ((null lst) nil)
        ((atom (car lst)) (append (list (car lst)) (my-flatten (cdr lst))))
        (t (append (my-flatten (car lst)) (my-flatten (cdr lst))))))

(my-flatten '(a (b (c d) e))) => (A B C D E)
(my-flatten '(a)) => (A)
(my-flatten '((a))) => (A)
(my-flatten '(((a)))) => (A)
(my-flatten '(a (b))) => (A B)
(my-flatten '()) => NIL
(my-flatten '(())) => (NIL)
(my-flatten '(() () ((())))) => (NIL NIL NIL)

;;;; P08
(defun compress (lst)
  (labels ((f (cur l)
             (cond
               ((null l) (and cur (cons cur nil)))
               ((null cur) (f (car l) (cdr l)))
               ((eq cur (car l)) (f cur (cdr l)))
               (t (cons cur (f (car l) (cdr l)))))))
    (f nil lst)))

(compress '(a a a a b c c a a d e e e e)) => (A B C A D E)
(compress '()) => NIL
(compress '(a)) => (A)
(compress '(a b)) => (A B)
(compress '(a b b)) => (A B)
(compress '(a a b)) => (A B)
(compress '(a b c d e)) => (A B C D E)
(compress '(a a a a a)) => (A)
(compress '(a b c c c c c)) => (A B C)

;;;; P09
(defun pack (lst)
  (labels ((f (l cur ret)
             (cond
               ((null l) (append ret (list cur)))
               ((or (null cur) (eq (car cur) (car l)))
                (f (cdr l) (cons (car l) cur) ret))
               (t
                (f (cdr l) (cons (car l) nil) (append ret (list cur)))))))
    ;; append ではなくて,cons 使っていって,
    ;; 最後に nreverse する方がいいかも。
    ;; でも,nreverse は使える武器?
    (f lst nil nil)))

(pack '(a b)) => ((A) (B))
(pack '(a a b b)) => ((A A) (B B))
(pack '(a a a a b c c a a d e e e e)) => ((A A A A) (B) (C C) (A A) (D) (E E E E))
(pack '(a)) => ((A))
(pack '()) => (NIL)

;;;; P10
(defun encode (lst)
  (mapcar (lambda (l)
            (list (length l) (car l)))
          (pack lst)))

(encode '(a a a a b c c a a d e e e e)) => ((4 A) (1 B) (2 C) (2 A) (1 D) (4 E))
(encode '(a b)) => ((1 A) (1 B))
(encode '(a a b b)) => ((2 A) (2 B))
(encode '(a)) => ((1 A))
(encode '()) => ((0 NIL))