Sunday, March 31, 2013

Leveraging Sow to Simplify Loops

One of Mathematica's coolest list manipulation techniques is the Reap/Sow pattern. Using these functions together allows you to build up multiple collections at once in a decoupled manner.

To understand this idea and when it might make a difference, consider how you would sort a list of integers by divisor. What I mean is, given the list \[\{12,13,14,15,21,24,28,41,47,49,55\}\] sort it into the following lists based on divisor: \[\begin{align} 2 &\rightarrow \{12,14,24,28\} \\ 3 &\rightarrow \{12,15,21,24\} \\ 5 &\rightarrow \{15,55\} \end{align}\] (and here it's okay if one item shows up in two lists)

You might think to do it by using a for-loop and storing each item in a named list depending on what it matches. But if you want a variable list of divisors? In this case, managing the list of results can get a little tricky.

The Reap/Sow pattern presents a different approach: when important values are computed inside a function they can be "sown" with Sow, which means they bubble up the call stack until a matching Reap expression is encountered. You can use a Reap expression to process or discard sown values as you see fit.

An implementation of the divisor sorting algorithm using Reap and Sow might look something like this:

SortByDivisors[numbers_,divisors_]:=Reap[
  For[i=1, i \(\leq\) Length[numbers], i++,
    For[j=1, j \(\leq\) Length[divisors],j++
      n = numbers[[i]];
      d = divisors[[i]];
      If[Mod[n,d] == 0, Sow[n,d]];
    ];
  ];, n_, Rule][[2]]; 


And it will return a collection of Rules, each of which has a divisor as the key and a corresponding list of multiples as the value.

No comments:

Post a Comment