Ah right! I knew I had to use gen/choose for this,
I am still grokking bind :)

Thanks for your help!
That indeed did the trick for me :)

One thing I am clear about is,
If I use gen/return it says it'll not shrink.
Does that mean when a test fails for a certain order, it won't try to
shrink that order of collection?
Because I have used a gen/return at the end of the generator?

Thanks again for your help! :)

On Fri, Aug 14, 2015 at 8:13 PM, Carlo Zancanaro <carlozancan...@gmail.com>
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 <firesof...@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 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.
>

-- 
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