Interesting idea. Will look into how shuffle works and see if I can adapt
that instead.
Thanks :)

On Sat, Aug 15, 2015 at 7:56 AM, Gary Fredericks <fredericksg...@gmail.com>
wrote:

> Another kind of approach that would be worth trying is adapting
> test.check's own shuffle generator
> <https://github.com/clojure/test.check/blob/e3256cbaa3a98b1d688475fe190aa97ad255e08b/src/main/clojure/clojure/test/check/generators.clj#L447-465>.
> It generates a sequence of pairs of indexes and then swaps the elements at
> those indexes. The benefits are that you avoid the stack issues and also
> other disadvantages that come with using bind.
>
> I tried one that only did adjacent swaps, and only when they didn't
> violate the constraint, but it took a lot of swaps for it to get really
> mixed up. I think something more clever could be better.
>
> Gary
>
> On Friday, August 14, 2015 at 9:43:52 AM UTC-5, Carlo wrote:
>>
>> Hey Mayank!
>>
>> Similarly to your attempt last time, you need to use gen/bind to get the
>> result of a generator which you can then use to make a new generator.
>>
>> (defn- rand-interleave* [coll acc]
>>   (if (seq coll)
>>     (gen/bind (gen/choose 0 (dec (count coll)))
>>               (fn [index]
>>                 (let [value (first (get coll index))
>>                       coll (->> (update-in coll [index] next)
>>                                 (remove empty?)
>>                                 vec)]
>>                   (rand-interleave* coll (conj acc value)))))
>>     (gen/return acc)))
>>
>> (defn rand-interleave [& colls]
>>   (rand-interleave* (vec colls) []))
>>
>> The (gen/choose 0 (dec (count coll))) is similar to your rand-count
>> function, then the generated number is passed to the function as result.
>> Writing it this way will shrink towards the (apply concat args) (ie. as
>> it shrinks it will move towards just concatenating the arguments).
>>
>> In terms of the recursion: this will eventually overflow the stack. I
>> don't know of a way to trampoline generators, so I don't know how to avoid
>> that. (This is a bit of a recurring problem with monadic code in Clojure, I
>> feel, as algo.monads had a similar problem last time I checked.) For the
>> moment I'm just ignoring this theoretical problem until it becomes a
>> practical problem.
>>
>> I hope that helps!
>>
>> Carlo
>>
>> On 14 August 2015 at 23:39, Mayank Jain <fires...@gmail.com> wrote:
>>
>>> Hi Everyone,
>>>
>>> Here's the problem I am facing,
>>> I need to write a generator which takes any number of sequences,
>>> interleaves them but maintains the order within each sequence.
>>> Assume each sequence has at least one element.
>>>
>>> For example:
>>>
>>> (rand-interleave [1 2 3 4] [:a :b] [:A :B :C :D :E])
>>>> => [:a 1 2 :b :A :B :C 3 :D 4 :E]
>>>
>>>
>>> (rand-interleave [1 2 3 4])
>>>> => [1 2 3 4]
>>>
>>>
>>> (rand-interleave [1])
>>>> => [1]
>>>
>>>
>>> (rand-interleave [1] [:a] [:A])
>>>> => [:a 1 :A]
>>>
>>>
>>> I have been able to write this down as clojure functions.
>>> But I am unable to convert this into a test.check generator.
>>>
>>> Specifically:
>>>
>>>    - How to pass random index count without using rand-int i.e. use
>>>    gen/choose
>>>    - How do I write recursive functions which play well with test.check
>>>
>>> Here's my take on it (without the generators).
>>>
>>> (defn- first-nth
>>>>   "(first-nth [[1 2 3 4] [:a :b :c :d]]
>>>>                   1)
>>>>    => :a"
>>>>   [coll n]
>>>>   (first (nth coll n)))
>>>
>>>
>>>
>>> (defn- next-nth
>>>>   "(next-nth [[1 2 3 4] [:a :b :c :d]]
>>>>                   1)
>>>>    => [[1 2 3 4] (:b :c :d)]"
>>>>   [coll n]
>>>>   (->> n
>>>>        (nth coll)
>>>>        next
>>>>        (assoc coll n)
>>>>        (remove nil?)
>>>>        vec))
>>>
>>>
>>>
>>> (defn- rand-count
>>>>   [coll]
>>>>   (rand-int (count coll)))
>>>
>>>
>>>
>>> (defn- rand-interleave*
>>>>   [coll acc]
>>>>   (let [n (rand-count coll)]
>>>>     (if (not-empty coll)
>>>>       (rand-interleave* (next-nth coll n)
>>>>                                   (conj acc
>>>>                                           (first-nth coll n)))
>>>>       acc)))
>>>
>>>
>>>
>>> (defn rand-interleave
>>>>   [& args]
>>>>   ;; Make args a vector as I would like to
>>>>   ;; look up elements by their index values.
>>>>   (rand-interleave* (vec args) []))
>>>
>>>
>>> Looking forward to any suggestions on how to solve it :)
>>>
>>> Thanks,
>>> Mayank.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to