Combining lists of 2D points

Hi all,

I’m trying to solve a somewhat simple problem, but I’m using it as a proxy to better understand the Map/Thread/MapThread aspects of the language, …
I have 2 lists that I want to combine/add. The list elements are 2D points, but the lists could be arbitrarily long i.e.

aa = {{Ax, Ay}, {Bx, By}, {Cx, Cy}}
bb = {{x1, y1}, {x2, y2}, {x3, y3}, {x4, y4},{x5, y5}}

and I want to combine the lists to get an output that is :

out = {{Ax + x1, Ay + y1}, {Ax + x2, Ay + y2}, {Ax + x3, Ay + y3}, {Ax + x4,Ay + y4}, {Bx + x1, By + y1}, {Bx + x2, By + y2}, {Bx + x3,By + y3}, {Bx + x4, By + y4}, {Cx + x1, Cy + y1}, {Cx + x2,Cy + y2}, {Cx + x3, Cy + y3}, {Cx + x4, Cy + y4}}

I can do this with a Table command, i.e.

In[1]:= out = Flatten[Table[u + v, {u, aa}, {v, bb}], 1]
Out[1]= {{Ax + x1, Ay + y1}, {Ax + x2, Ay + y2}, {Ax + x3, Ay + y3}, {Ax + x4, Ay + y4}, {Bx + x1, By + y1}, {Bx + x2, By + y2}, {Bx + x3, By + y3}, {Bx + x4, By + y4}, {Cx + x1, Cy + y1}, {Cx + x2, Cy + y2}, {Cx + x3, Cy + y3}, {Cx + x4, Cy + y4}}

However, I was trying to figure out how this could be done using a Map/Thread/MapThread based approach. I got as far as:

In[2]:= Map[aa[[1]] + # &, bb]
Out[2]= {{Ax + x1, Ay + y1}, {Ax + x2, Ay + y2}, {Ax + x3,Ay + y3}, {Ax + x4, Ay + y4}}

or

In[3]:= gg[arg1_, arg2_] := Map[arg1 + # &, arg2]
In[4]:= gg[aa[[1]], bb]
Out[4]= {{Ax + x1, Ay + y1}, {Ax + x2, Ay + y2}, {Ax + x3, Ay + y3}, {Ax + x4, Ay + y4}}

But taking it the next step and having the function take in a list of points aa instead of just one has been problematic (that is without ending up with an unwieldy, messy pit of code). I think part of my problem is that the function Plus acting on a list just gives back the list, i.e.

In[5]:= Plus[{a, b, c}]
Out[5]= {a, b, c}

Thanks of any words of wisdom, and happy new year to all.

I think what you want is Outer[Plus, aa, bb] and then Flatten to get to the level of nesting you want.

Concise approaches are:

you could use the Tuples function to get the combinations and then, simply, Apply the Plus function:

Plus @@@ Tuples[{aa, bb}] 

Or, as Frank suggested, the outer function with a fourth argument for the level specification, and then flattening:

Flatten[Outer[Plus,aa,bb, 1],1]

I Hope this helps T Saab..

Your function gg already maps over bb, so map that over aa.

out === Join @@ Map[gg[#, bb] &, aa] 
out === Flatten[gg[#, bb] & /@ aa, 1]

Tupels and Outer is a better way to go for your exampel problem. To get Thread to work with items of different level depth and length, it is tricky.

out === Flatten[ Function[{a, b}, Map[Plus[a, #] &, b]] @@@ (Thread[{aa, b}] /. b -> bb), 1]

In the above example the operation being applied to the result of Thread you already designated as, gg

out === Flatten[gg @@@ (Thread[{aa, b}] /. b -> bb), 1]

Thank you all, this was very helpful.

The Plus@@@Tuples was the approach that I had originally wanted to translate from “gray-matter” language into mathematica language. Didn’t realize the correspondence was quite so literal :slight_smile:

P.S. Christopher, if I may ask a related question re. your first suggstion:

gg[arg1_, arg2_] := Map[arg1 + # &, arg2]
Map[gg[#, bb] &, aa] 

In a sense this looks like a 2-level deep set of pure functions. I was wondering if this can be done in 1 step, i.e.
replace the # in (Map[gg[#, bb] &, aa]) with (Map[gg[#, bb] &, aa] )

Map[ Map[#L1 + #L2 &, bb] &, aa]

#L1 and #L2 are meant to represent the arguments passed to the different levels of pure function. Is that possible in the mathematica syntax?

You are absolutly correct in the observation, that the generic variable # inside (# + # &) has no way of knowing the first # comes from the outside Map and the second # comes from the inside Map. This inside and outside indexing is already handeled for you by Table, but still you have to set up the variables to be distinguishable using u and v, in Table[u + v, {u, aa}, {v, bb}], for example. The same thing can be done for a pure function, if you replace the function signifier & with the raw head Function.

Map[Function[{u}, Map[u + # &, bb]], aa]
Map[Function[{u}, Map[Function[{v}, u + v], bb]], aa]