In the project that I am working on, I came across an interesting problem that I am interested in other solutions about. I'm in the middle of reading The Little Schemer, so I'm trying some recursion methods. I am wondering if there is another way to do this with recursion, and is also interested if there is an approach without using recursion.
The task is to take a sequence and break it into seq from seqs, taking every nth element. For example, this vector:
[ :a :b :c :d :e :f :g :h :i ]
when divided by n = 3 will generate seq
((:a :d :g) (:b :e :h) (:c :f :i))
and with n = 4:
((:a :e :i) (:b :f) (:c :g) (:d :h))
etc. I solved this using two functions. The first creates internal seqs, and the other combines them. Here are my functions:
(defn subseq-by-nth "Creates a subsequence of coll formed by starting with the kth element and selecting every nth element." [coll kn] (cond (empty? coll) nil (< (count coll) n) (seq (list (first coll))) :else (cons (nth coll k) (subseq-by-nth (drop (+ nk) coll) 0 n)))) (defn partition-by-nth "" ([coll n] (partition-by-nth coll nn)) ([coll ni] (cond (empty? coll) nil (= 0 i) nil :else (cons (subseq-by-nth coll 0 n) (partition-by-nth (rest coll) n (dec i))))))
I am not entirely happy that the "partitioning" function has multiple arity just for recursion, but could not see another way.
This seems to work fine with all test cases. Is this a decent approach? Is it too complicated? Is there a way to do this without recursion, or perhaps in a single recursive function?
Thanks for the suggestions. I am new to both Clojure and Lisp, so I collect various methods when I go.
source share