#lang racket
(require srfi/41)
;; 順列
(define (perm xs r)
(if (zero? r)
'(())
(append-map (lambda (x)
(map (lambda (ys)
(cons x ys)) (permutations (remove x xs) (- r 1))))
xs)))
;; 手抜き版
(define (comb xs r)
(map set->list (set->list (list->set (map list->set (perm xs r))))))
;; 集合版
(define (set-combination st r)
(cond ((zero? r) (set (set)))
((= r (set-count st)) (set st))
(else (let ((s (set-rest st)))
(set-union
(for/set ((i (set-combination s (- r 1))))
(set-add i (set-first st)))
(set-combination s r))))))
;; リスト版
(define (combination xs r)
(cond ((zero? r) '(()))
((= r (length xs)) `(,xs))
(else (let ((s (cdr xs)))
`(,@(map (lambda (x)
(cons (car xs) x)) (combination s (- r 1)))
,@(combination s r))))))
;; 遅延評価版
(define (stream-combination strm r)
(cond ((zero? r) (stream stream-null))
((= r (stream-length strm)) (stream strm))
(else (let ((s (stream-cdr strm)))
(stream-append
(stream-map (lambda (x)
(stream-cons (stream-car strm) x))
(stream-combination s (- r 1)))
(stream-combination s r))))))
I2xhbmcgcmFja2V0CgoocmVxdWlyZSBzcmZpLzQxKQoKOzsg6aCG5YiXCgooZGVmaW5lIChwZXJtIHhzIHIpCiAgKGlmICh6ZXJvPyByKQogICAgICAnKCgpKQogICAgICAoYXBwZW5kLW1hcCAobGFtYmRhICh4KQogICAgICAgICAgICAgICAgICAgIChtYXAgKGxhbWJkYSAoeXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChjb25zIHggeXMpKSAocGVybXV0YXRpb25zIChyZW1vdmUgeCB4cykgKC0gciAxKSkpKQogICAgICAgICAgICAgICAgICB4cykpKQoKOzsg5omL5oqc44GN54mICgooZGVmaW5lIChjb21iIHhzIHIpCiAgKG1hcCBzZXQtPmxpc3QgKHNldC0+bGlzdCAobGlzdC0+c2V0IChtYXAgbGlzdC0+c2V0IChwZXJtIHhzIHIpKSkpKSkKCjs7IOmbhuWQiOeJiAoKKGRlZmluZSAoc2V0LWNvbWJpbmF0aW9uIHN0IHIpCiAgKGNvbmQgKCh6ZXJvPyByKSAoc2V0IChzZXQpKSkKICAgICAgICAoKD0gciAoc2V0LWNvdW50IHN0KSkgKHNldCBzdCkpCiAgICAgICAgKGVsc2UgKGxldCAoKHMgKHNldC1yZXN0IHN0KSkpCiAgICAgICAgICAgICAgICAoc2V0LXVuaW9uCiAgICAgICAgICAgICAgICAgKGZvci9zZXQgKChpIChzZXQtY29tYmluYXRpb24gcyAoLSByIDEpKSkpCiAgICAgICAgICAgICAgICAgICAoc2V0LWFkZCBpIChzZXQtZmlyc3Qgc3QpKSkKICAgICAgICAgICAgICAgICAoc2V0LWNvbWJpbmF0aW9uIHMgcikpKSkpKQoKOzsg44Oq44K544OI54mICgooZGVmaW5lIChjb21iaW5hdGlvbiB4cyByKQogIChjb25kICgoemVybz8gcikgJygoKSkpCiAgICAgICAgKCg9IHIgKGxlbmd0aCB4cykpIGAoLHhzKSkKICAgICAgICAoZWxzZSAobGV0ICgocyAoY2RyIHhzKSkpCiAgICAgICAgICAgICAgICBgKCxAKG1hcCAobGFtYmRhICh4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAoY29ucyAoY2FyIHhzKSB4KSkgKGNvbWJpbmF0aW9uIHMgKC0gciAxKSkpCiAgICAgICAgICAgICAgICAgICxAKGNvbWJpbmF0aW9uIHMgcikpKSkpKQoKOzsg6YGF5bu26KmV5L6h54mICgooZGVmaW5lIChzdHJlYW0tY29tYmluYXRpb24gc3RybSByKQogIChjb25kICgoemVybz8gcikgKHN0cmVhbSBzdHJlYW0tbnVsbCkpCiAgICAgICAgKCg9IHIgKHN0cmVhbS1sZW5ndGggc3RybSkpIChzdHJlYW0gc3RybSkpCiAgICAgICAgKGVsc2UgKGxldCAoKHMgKHN0cmVhbS1jZHIgc3RybSkpKQogICAgICAgICAgICAgICAgKHN0cmVhbS1hcHBlbmQKICAgICAgICAgICAgICAgICAoc3RyZWFtLW1hcCAobGFtYmRhICh4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0cmVhbS1jb25zIChzdHJlYW0tY2FyIHN0cm0pIHgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdHJlYW0tY29tYmluYXRpb24gcyAoLSByIDEpKSkKICAgICAgICAgICAgICAgICAoc3RyZWFtLWNvbWJpbmF0aW9uIHMgcikpKSkpKQ==