Re: Challenge!

*To*: mathgroup at christensen.cybernetics.net*Subject*: [mg926] Re: Challenge!*From*: villegas (Robert Villegas)*Date*: Wed, 3 May 1995 00:05:11 -0400*Organization*: Wolfram Research, Inc.

> I have two lists of equal length M. > > I wish to generate a third list also of length M, where the i th element > of this list is either the i th element of the first list, or the i th > element of the second list. > > It should be equally probable that the new element be chosen from the > first or second list. > > eg. I have a list {a,b,c,d,e,f,g} > and another {A,B,C,D,E,F,G} > > valid answers would be: > {a,B,C,d,e,F,G} > {a,b,c,d,E,f,g} > {A,B,C,D,e,f,G} > etc. Paul, One way of looking at this is that you want to take corresponding elements of the two lists, like a and A, and apply a function to them, f[a, A], where f means "pick one of your arguments at random". MapThread will do this: take two lists, feed their first arguments to f, then feed their second arguments to f, and so on, giving you the list of f-results at the end. A diagram makes it a little clearer how you're gluing the two lists together with f: {a1 , a2 , a3 , . . . , aM} | | | | f f f f | | | | {b1 , b2 , b3 , . . . , bM} So let's use "glue" f that picks a random element: In[7]:= list1 = {a, b, c, d, e, f, g} Out[7]= {a, b, c, d, e, f, g} In[8]:= list2 = {A, B, C, D, E, F, G} Out[8]= {A, B, C, D, E, F, G} In[9]:= MapThread[Part[{#1, #2}, 1 + Random[Integer] ]&, {list1, list2}] Out[9]= {A, B, c, d, E, F, G} Note that Random[Integer] is a short way of generating a random integer 0 or 1 (related: Random[Real] generates a random Real from 0 to 1, and Random[Complex] generates a random Complex whose parts are real numbers from 0 to 1). We can make it easy to generate more random selections from the two by making a delayed assignment to a variable 'randomSelection'. Any time we evaluate 'randomSelection', like in a Table, we get a different random selection from the two lists. In[10]:= randomSelection := MapThread[Part[{#1, #2}, 1 + Random[Integer] ]&, {list1, list2}] In[11]:= Table[randomSelection, {6}] //TableForm Out[11]//TableForm= a b C D E F G a B C d e F g A B C D E f G A b c D E F G a b C D E f g a B c D e F G This method of storing a command or program in a symbol is given in Roman Maeder's _Programming in Mathematica_ (2nd ed), section 5.5.3. MapThread is happy to work with any number of lists, so we can use it to randomly select from k lists instead of just 2, with essentially no complications in the command. Here's the same technique applied to seven lists: In[18]:= lists = Array[a, {7, 5}] ; TableForm[lists] Out[18]//TableForm= a[1, 1] a[1, 2] a[1, 3] a[1, 4] a[1, 5] a[2, 1] a[2, 2] a[2, 3] a[2, 4] a[2, 5] a[3, 1] a[3, 2] a[3, 3] a[3, 4] a[3, 5] a[4, 1] a[4, 2] a[4, 3] a[4, 4] a[4, 5] a[5, 1] a[5, 2] a[5, 3] a[5, 4] a[5, 5] a[6, 1] a[6, 2] a[6, 3] a[6, 4] a[6, 5] a[7, 1] a[7, 2] a[7, 3] a[7, 4] a[7, 5] In[19]:= MapThread[Part[{##}, Random[Integer, {1, 7}]]&, lists] Out[19]= {a[3, 1], a[2, 2], a[3, 3], a[7, 4], a[2, 5]} A different method from MapThread is Table, and gives a command that is equally short: In[20]:= Table[Part[lists, Random[Integer, {1, 7}], i], {i, 5}] Out[20]= {a[4, 1], a[4, 2], a[2, 3], a[1, 4], a[4, 5]} I'm not sure which one holds up better in timing tests for either a large number of lists, or lists with a large number of elements. It would be interesting to do some tests. Robby Villegas