3の倍数と3が付く数字のときだけアホになります(1)

http://d.hatena.ne.jp/kikaineko/20080430を見て、作りたくなったので作ってみた。
なんか、80分もかかった上にごちゃごちゃしたコードになってしまった。
一応、9999まで数えられるけど、ひゃくを読み直すのが面倒で中途半端。
まあ、折角作ったので載せておく。

(setq num-char '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
      n-cnt-1 (mapcar #'cons num-char '("ぜろ" "いち" "に" "さん" "よん" "ご" "ろく" "なな" "はち" "きゅう"))
      a-cnt-1 (mapcar #'cons num-char '("ずぇーろっ" "うぃーちい" "にぃ" "すゎーん" "ゆぁーん" "ぐぉ" "りょくぁ" "ぬあーな" "ふぁっちぃ" "きゅーう"))
      n-cnt-b '("" "じゅう" "ひゃく" "せん")
      a-cnt-b '("" "ぜーう" "ふぉあくっ" "すえーん"))

(defun nabe-cnt (to &optional (from 1))
  (let ((f (> from to)))
    (if f (rotatef from to))
    (if (< from 0) (setq from 0))
    (if (> from 9999) (setq from 9999))
    (if (< to 0) (setq to 0))
    (if (> to 9999) (setq to 9999))
    (let ((i (1- from)) l)
      (while (<= (incf i) to)
        (let ((i-l (coerce (format nil "~A" i) 'list)))
          (setq cnt '(n-cnt-1 n-cnt-b))
          (push (nabe-cnt-sub (reverse i-l)
                              (if (or (zerop (mod i 3))
                                      (member #\3 i-l))
                                  (list a-cnt-1 a-cnt-b)
                                (list n-cnt-1 n-cnt-b)))
                l)))
      (if f l (reverse l)))))

(defun nabe-cnt-sub (rev-num-ls cnt-ls &optional (stack 0))
  (concatenate 'string
               (if (cdr rev-num-ls)
                   (nabe-cnt-sub (cdr rev-num-ls) cnt-ls (1+ stack)))
               (if  (or (and (> stack 0)
                             (member (car rev-num-ls) '(#\0 #\1)))
                        (and (= stack 0)
                             (equal (car rev-num-ls) #\0)))
                   nil
                 (cdr (assoc (car rev-num-ls) (car cnt-ls))))
               (if (equal (car rev-num-ls) #\0) nil (elt (cadr cnt-ls) stack))))

実行結果はこんな感じ。

(dolist (x (nabe-cnt 40))
		(format t "~A~%" x))
いち
に
すゎーん
よん
ご
りょくぁ
なな
はち
きゅーう
じゅう
じゅういち
ぜーうにぃ
ぜーうすゎーん
じゅうよん
ぜーうぐぉ
じゅうろく
じゅうなな
ぜーうふぁっちぃ
じゅうきゅう
にじゅう
にぃぜーううぃーちい
にじゅうに
にぃぜーうすゎーん
にぃぜーうゆぁーん
にじゅうご
にじゅうろく
にぃぜーうぬあーな
にじゅうはち
にじゅうきゅう
すゎーんぜーう
すゎーんぜーううぃーちい
すゎーんぜーうにぃ
すゎーんぜーうすゎーん
すゎーんぜーうゆぁーん
すゎーんぜーうぐぉ
すゎーんぜーうりょくぁ
すゎーんぜーうぬあーな
すゎーんぜーうふぁっちぃ
すゎーんぜーうきゅーう
よんじゅう
nil

このコードの作り方だと、例外的な処理が割と面倒。変にまとめたりしないで、素朴に作った方が楽かも。
次はそれで試してみよう。
確かに、このくらいであれば、データをそのまま入力するイメージでプログラムした方が良いかも知れない。