Generating lists of sequences of specified lengths I'm writing a program that uses a Genetic Algorithm to "intelligently brute force" our schedule at work. We typically have issues with creating schedules, so I thought using my new GA library to tackle the problem would be a neat exercise.

One of the very first functions I wrote seems overly complex though. It works as intended, but I worry that it could be simplified by making use of higher-order looping constructs instead of a raw loop:

(defn cut-genes-into-day-blocks
  "Cuts the genes into blocks. Each block will have as many genes are there are shifts that day.
  shifts-per-day should be a list (whose length matches the period length) containing how many shifts exist for each day of the period.

  For example, if a period is 14 days, and there are 5 shifts on weekdays, and 2 shifts on weekends,
   shifts-per-day would be [5 5 5 5 5 2 2 5 5 5 5 5 2 2]."
  [genes shifts-per-day]
  (loop [rem-genes genes
         [n-shifts &amp; rem-days] shifts-per-day
         acc []]

    (if n-shifts
      (let [[block rest-genes] (split-at n-shifts rem-genes)]
        (recur rest-genes
               rem-days
               (conj acc block)))

      acc)))


As the docs mention, the purpose of this function is to take a gene sequence, and cut it into blocks where each block has as many elements as there are shifts in that day. An example usage (using dummy genes created by range) is:

(let [shifts-per-day [5 5 5 5 5 2 2 5 5 5 5 5 2 2]
      total-shifts (reduce + 0 shifts-per-day)
      genes (vec (range total-shifts))]
  (cut-genes-into-day-blocks genes shifts-per-day))

[(0 1 2 3 4) ; &lt;---- Each number represents a person working that day
 (5 6 7 8 9) ; &lt;---- 5 different people/shifts on weekdays...
 (10 11 12 13 14)
 (15 16 17 18 19)
 (20 21 22 23 24)
 (25 26) ; &lt;---- ... and 2 shifts on the weekends
 (27 28)
 (29 30 31 32 33)
 (34 35 36 37 38)
 (39 40 41 42 43)
 (44 45 46 47 48)
 (49 50 51 52 53)
 (54 55)
 (56 57)]


This function is overly chunky though and contains a few things that I've run into in the past that I'd like suggestions on:


The "deconstruct the head from tail, then check if the first element is valid" "pattern". I use it a lot in my code whenever I'm iterating over a list using loop. Use the rest operator to pop the first element off, then check if it's actually valid before using it.
The fact that the loop requires 3 "state variables" is unfortunate. It would be nice if the accumulator was implicit somehow. I know that using reduce over shifts-per-day would et rid of one of the bits of information needing to be maintained, but there are two accumulators in use here (acc and rem-genes), and I've found reducing when more than one accumulator is necessary to be very messy and not worth the trouble.
Any other tips that you think are worth mentioning would be appreciated.
Your function seems very well suited to the Clojure iterate function, which takes a function that turns state into state:

(def shifts [5 5 5 5 5 2 2 5 5 5 5 5 2 2])
(def total-shifts (apply + shifts))
(def genes (vec (range total-shifts)))

(defn transition [[answer shifts-remaining genes-remaining]]
  (let [[num-shifts &amp; more-shifts] shifts-remaining
        [genes-in-day rest-of-genes] (split-at num-shifts genes-remaining)]
    [(conj answer genes-in-day) more-shifts rest-of-genes]))

(-&gt;&gt; (iterate transition [[] shifts genes])
     (drop (count shifts))
     ffirst)