patternMinor
Enumerate k-combinations in Clojure (P26 from 99 problems)
Viewed 0 times
clojurecombinationsp26problemsfromenumerate
Problem
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:
My basic solution is to take each item from the given sequence (
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.
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
(> 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.
Solution
I'm currently reading "Joy of Clojure" so I'm (very) far from being "fluent" in Clojure but what I noticed is:
Here's my code:
- 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)))))Code Snippets
(defn subsets [n items]
(cond
(= n 0) '(())
(empty? items) '()
:else (concat (map
#(cons (first items) %)
(subsets (dec n) (rest items)))
(subsets n (rest items)))))Context
StackExchange Code Review Q#8930, answer score: 3
Revisions (0)
No revisions yet.