Mathematica 9 is now available
Services & Resources / Wolfram Forums
-----
 /
MathGroup Archive
1995
*January
*February
*March
*April
*May
*June
*July
*August
*September
*October
*November
*December
*Archive Index
*Ask about this page
*Print this page
*Give us feedback
*Sign up for the Wolfram Insider

MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

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


  • Prev by Date: Module/Block problem (passing pointers?)
  • Next by Date: Re: RealDigits
  • Previous by thread: Re: Functional programming puzzle
  • Next by thread: Re: Functional programming puzzle