1

lispの任意のリストから、重複する組み合わせを持たずに、そのリストの要素の2つの要素の組み合わせを取得したい((ab)=(ba)を意味し、1つは削除する必要があります)

たとえば、(abcd)のリストがある場合、

取得したい((ab)(ac)(ad)(bc)(bd)(cd))

4

5 に答える 5

5
(defun combinations (list)
  (loop for (a1 . r1) on list
        nconc (loop for a2 in r1 collect (list a1 a2))))


CL-USER 172 > (combinations '(a b c d))
((A B) (A C) (A D) (B C) (B D) (C D))
于 2013-02-07T21:52:34.127 に答える
2

私はあなたを正しく理解していると仮定して、私はmapcar友達を使います。

(defun pair-with (elem lst)
  (mapcar (lambda (a) (list elem a)) lst))

(defun unique-pairs (lst)
  (mapcon (lambda (rest) (pair-with (car rest) (cdr rest)))
          (remove-duplicates lst)))

それはあなたを可能にするはずです

CL-USER> (unique-pairs (list 1 2 3 4 5))
((1 2) (1 3) (1 4) (1 5) (2 3) (2 4) (2 5) (3 4) (3 5) (4 5))
CL-USER> (unique-pairs (list :a :b :c :a :b :d))
((:C :A) (:C :B) (:C :D) (:A :B) (:A :D) (:B :D))

怖くない場合はloop、2番目のものをもう少し明確に書くこともできます

(defun unique-pairs (lst)
  (loop for (a . rest) on (remove-duplicates lst)
        append (pair-with a rest)))

代わりは。loopsappendディレクティブは、同じ名前の関数よりも効率的であると私は合理的に確信しています。

于 2013-02-07T21:36:03.503 に答える
1

これは、ループを使用しないことを除いて、原則としてRainerのJoswigの回答に似ています。

(defun combinations (list)
  (mapcon (lambda (x) (mapcar (lambda (y) (list (car x) y)) (cdr x))) list))

あなたの例について私を混乱させる1つのこと(a a)は、希望する結果の口頭での説明と一致することですが、結果の例ではそれを除外しています。

于 2013-02-08T16:20:16.377 に答える
1

スキームソリューション:

(define (lol lst)
  (let outer ((lhs lst))
    (if (null? lhs)
        '()
        (let inner ((rhs (cdr lhs)))
          (if (null? rhs)
              (outer (cdr lhs))
              (cons (list (car lhs) (car rhs)) (inner (cdr rhs))))))))

そして同じもののCommonLisp翻訳:

(defun lol (list)
  (labels ((outer (lhs)
             (and lhs (labels ((inner (rhs)
                                 (if rhs
                                     (cons (list (car lhs) (car rhs))
                                           (inner (cdr rhs)))
                                     (outer (cdr lhs)))))
                        (inner (cdr lhs))))))
    (outer list)))

申し訳ありませんが、私はCommon Lisperではないので、これが醜くなりすぎないことを願っています。:-)

于 2013-02-07T18:39:53.353 に答える
0

これが私自身の最初の答えです。完全に効率的ではないかもしれませんが、問題は解決します。

(remove nil (let ((res))
             (dotimes (n (length test-list) res)
                (setq res
                     (append res
                        (let ((res2) (rest-list (remove (nth n test-list) test-list)))
                         (dotimes (m (length rest-list) res2)
                            (setq res2
                                 (append res2
                                   (list (if (< (nth n test-list) (nth m rest-list))
                                         (list (nth n test-list) (nth m rest-list))
                                          nil)))))))))))

9行目の「ifステートメント」を削除すると、結果にも重複が含まれ、結果は次のようになります。

((a b) (a c) (a d) (a a) (b a) (b c) (b d) (b b) 
 (c a) (c b) (c d) (c c) (d a) (d b) (d c) (d d))
于 2013-02-07T19:03:14.793 に答える