combination.el

要素数Nの配列からK個を取る組み合わせを作る必要があり、Emacsのsite-lispに実装があるかと思ったが見当たらなかった。そんなわけでElispで書いてみました。リストから順番に要素を取りながら組み合わせを作る手順は想像できたので以下を書いた。

(let ((numbers (list 1 2 3 4 5 6 7 8 9))
      (pickup 3))
  (cl-labels
      ((datasource
        (head tail result)
        (if (< (length tail)
               (- pickup (length head)))
            result
          (datasource head
                      (cdr tail)
                      (cons (cons (cons (car tail)
                                        head)
                                  (cdr tail))
                            result))))
       (combination
        (source)
        (let ((sample (car source)))
          (if (< (length (car sample)) pickup)
              (combination (nconc (cdr source)
                                  (datasource (car sample)
                                              (cdr sample)
                                              nil)))
            (mapcar #'car source)))))
    (combination (datasource nil numbers nil))))

ひとつの関数の再帰で可能かとも思ったが、max-lisp-eval-depthエラーのため2段階に分けた。さらに流れが追いづらく、分かりにくいコードとなっているので、また考え直したいと思う。