#:g1: closでL-99 (P26 指定した個数を抜き出す組み合わせ)

Posted 2008-06-13 09:14:00 GMT

-(http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html)
call-next-methodの連鎖で行くと、stringの次は、vectorになってしまって面倒臭いので、combination1という共通の補助メソッドを作成して呼んでいるわけなのですが、一番特定度の低いメソッドを呼び出す定番の方法があったりするんでしょうか?
再帰と、call-next-methodと、ディスパッチが混ざると、大分スパゲッティな感じです…。
再帰の度にlengthが呼ばれるのもどうしたものかと…。

(combination 3 '(a b c d e f))
;==> ((A B C) (A B D) (A B E) (A B F) ...

(combination 3 #(a b c d e f)) ;==> (#(A B C) #(A B D) #(A B E) #(A B F) ...

(combination 3 "abcdef") ;==> ("abc" "abd" "abe" "abf" "acd" "ace" "acf" ...

(defgeneric COMBINATION (n sequence) (:documentation "P26 (**) Generate the combinations of K distinct objects chosen from the N elements of a list"))

(defmethod COMBINATION :around ((n integer) (sequence sequence)) (if (not (<= 1 n (length sequence))) () (call-next-method)))

(defmethod COMBINATION ((n integer) (sequence string)) (combination1 n sequence 'string)) (defmethod COMBINATION ((n (eql 1)) (sequence string)) (map 'list #'string sequence))

(defmethod COMBINATION ((n integer) (sequence vector)) (combination1 n sequence 'vector)) (defmethod COMBINATION ((n (eql 1)) (sequence vector)) (map 'list #'vector sequence))

(defmethod COMBINATION ((n integer) (sequence list)) (combination1 n sequence 'list)) (defmethod COMBINATION ((n (eql 1)) (sequence list)) (map 'list #'list sequence))

(defmethod COMBINATION1 ((n integer) (sequence sequence) type) `(,@(mapcar (lambda (i) (concatenate type (subseq sequence 0 1) i)) (COMBINATION (1- n) (subseq sequence 1))) ,@(COMBINATION n (subseq sequence 1))))


comments powered by Disqus