Re: Functional programming puzzle

*To*: mathgroup at christensen.cybernetics.net*Subject*: [mg1838] Re: Functional programming puzzle*From*: drc at gate.net (David Cabana)*Date*: Mon, 7 Aug 1995 20:24:47 -0400

In article <DCGM0w.5GH at wri.com>, "Wm. Martin McClain" <wmm at chem.wayne.edu> wrote: >Dear functional programers: > >Let ptList = {{1,1,2},{2,1,3},{1,3,2}}; > >I want a matrix of distances between the points in ptList. >Any human would think you could get it with > >Rij[a_,b_]:=Sqrt[(a-b).(a-b)] > >followed by > >Outer[Rij,ptList,ptList] > >But Mathematica returns a mess, because Outer seems >to Flatten the ptList before running the outer >product loops. ... >I am so frustrated that I am TEMPTED to do it with >explicit indices. > >Please, somebody help me before this happens. Let me comment further, since my prior posting neglected to answer the whole question, part of which I omitted above. One way to clean things up is to introduce a datatype, the point. Then things will work the way you want: In[54]:= ptList = {point[1,1,2], point[2,1,3], point[1,3,2]}; distance[x_point,y_point]:= Module[{a,b}, a=Apply[List,x]; b=Apply[List,y]; Sqrt[(a-b).(a-b)] ]; Outer[distance,ptList,ptList] Out[56]= {{0, Sqrt[2], 2}, {Sqrt[2], 0, Sqrt[6]}, {2, Sqrt[6], 0}} Here is what I left out earlier, and it is important if ptList has many entries. >Also, with explicit indices I could cut the number of >multiplies more than in half, because I know the >result will be symmetric, with only zeroes on the >diagonal. Is there some way to include this >knowledge in a functionally programmed version? Sure there is. Here's one way. First we introduce a function g; I couldn't think of a meaningful name for it. g[func_, x_, {a_,b__}]:= {func[x, a]} ~Join~ g[func, x, {b}] g[func_, x_, {a_}]:= {func[x, a]} Here's an example of what g does: In[81]:= g[f, 0, {1,2,3,4}] Out[81]= {f[0, 1], f[0, 2], f[0, 3], f[0, 4]} Using the distance function defined earlier, we now define In[82]:= Distances[{a_,b__}]:= {g[distance, a, {b}]} ~Join~ Distances[{b}] Distances[{a_}] := {} In[83]:= Distances[ptList] Out[83]= {{Sqrt[2], 2}, {Sqrt[6]}} Only three values are returned, rather than 9 as before. I am far from expert with Mma, so there may be several better ways to solve this problem. I think my approach has the virtue of being fairly understandable. The calls to Join could perhaps be replaced with calls to Prepend or Append (and appropriate mods to the code), resulting in more efficient list procesesing. Some time trials could determine that, but my purpose was simply to try solving the problem functionally. Hope this helps. -- David Cabana drc at gate.net