Enumerate k-combinations in Clojure (P26 from 99 problems) I've been playing with Clojure for the last few evenings, going through the well known 99 problems (I'm using a set adapted for Scala).


  Problem 26
  
  Given a set S and a no. of items K, returns all possible
  combinations of K items that can be taken from set S.


Here's my solution:

(defn combinations [k s]
  (cond
    (&gt; k (count s)) nil        ;not enough items in sequence to form a valid combination
    (= k (count s)) [s]        ;only one combination available: all items 
    (= 1 k) (map vector s)     ;every item (on its own) is a valid combination
    :else (reduce concat (map-indexed 
            (fn [i x] (map #(cons x %) (combinations (dec k) (drop (inc i) s)))) 
            s))))

(combinations 3 ['a 'b 'c 'd 'f])


My basic solution is to take each item from the given sequence (map-indexed) and recurse to generate combinations of size K - 1 from the remaining sequence. The termination conditions are described above.

I'm still a complete Clojure newbie and would welcome comments on structure, efficiency, readability, resemblance to idiomatic Clojure, etc. Feel free to be brutal, but please remember I've been doing Clojure for only a few hours :)

I'm less interested in alternative mathematical methods for generating k-combinations, more interested in feedback on whether this is passable Clojure.
I'm currently reading "Joy of Clojure" so I'm (very) far from being "fluent" in Clojure but what I noticed is:


your solution is clever but quite complicated, you use "imperative" habits like indexed iteration
try to keep with simple abstractions like sequence first and rest and the solution will work with any Clojure collection - see example below
your solution use cond with three checks for k - consider using condp


Here's my code:

(defn subsets [n items]
(cond
    (= n 0) '(())
    (empty? items) '()
    :else (concat (map
                    #(cons (first items) %)
                    (subsets (dec n) (rest items)))
                  (subsets n (rest items)))))