the sequence to be partitioned is a splittee
and the elements of split-points (aka. splitter
) marks the last element of a partition.
from your example:
splittee: [1 2 3 4 5 6]
splitter: [3 5]
result: ((1 2 3)(4 5)(6))
Because the resulting partitions is always a increasing integer sequence and increasing integer sequence of x
can be defined as start <= x < end
, the splitter elements can be transformed into end
of a sequence according to the definition.
so, from [3 5]
, we want to find subsequences ended with 4
and 6
.
then by adding the start
, the splitter
can be transformed into sequences of [start end]
. The start
and end
of the splittee is also used.
so, the splitter [3 5]
then becomes:
[[1 4] [4 6] [6 7]]
splitter transformation could be done like this
(->> (concat [(first splittee)]
(mapcat (juxt inc inc) splitter)
[(inc (last splittee))])
(partition 2)
there is a nice symmetry between transformed splitter
and the desired result.
[[1 4] [4 6] [6 7]]
((1 2 3) (4 5) (6))
then the problem becomes how to extract subsequences inside splittee
that is ranged by [start end]
inside transformed splitter
clojure has subseq
function that can be used to find a subsequence inside ordered sequence by start
and end
criteria. I can just map the subseq of splittee for each elements of transformed-splitter
(map (fn [[x y]]
(subseq (apply sorted-set splittee) <= x < y))
transformed-splitter)
by combining the steps above, my answer is:
(defn partition-by-seq
[splitter splittee]
(->> (concat [(first splittee)]
(mapcat (juxt inc inc) splitter)
[(inc (last splittee))])
(partition 2)
(map (fn [[x y]]
(subseq (apply sorted-set splittee) <= x < y)))))