t-sky
2/21/2012 - 4:52 AM

permutations-n

permutations-n

;; take N elements from LIS and make a row, in a weird way.
(define-macro (permutations-n lis n)
  (letrec ((make-loop
            (lambda (lis n core)
              (if (zero? n)
                  core
                  `(dolist (,(e-sym n) ,lis)
                     ,(make-loop lis (- n 1) core)))))
           (cons-each
            (lambda (n)
              (if (zero? n)
                  '()
                  `(cons ,(e-sym n) ,(cons-each (- n 1))))))
           (e-sym
            (lambda (n)
              (string->symbol (string-append "e" (number->string n))))))
  (let ((push-exp `(push! res ,(cons-each n))))
    `(let ((res '()))
       ,(make-loop lis n push-exp)
       (reverse! res)))))

;; Execution
gosh> (permutations-n '(a b c) 3)
((a a a) (a a b) (a a c) (a b a) (a b b) (a b c) (a c a) (a c b) (a c c) (b a a) (b a b) (b a c) (b b a) (b b b) (b b c) (b c a) (b c b) (b c c) (c a a) (c a b) (c a c) (c b a) (c b b) (c b c) (c c a) (c c b) (c c c))
gosh> (length (permutations-n '(a b c) 4))
81