0
$\begingroup$

I hope my title makes sense. The idea is the make a function in which a set of variables, $l_1$, $l_2$, etc. are accessible inside the innermost body of a nested (/folded) function. Each of these iterators would depend on the previous one, and takes an identical maximum value of Y.

I've chosen the Table command for this. The idea is that I have a helper list which builds {{l_1+bounds},{l_2+bounds},... X number of times, that is the last l is l_X.

To illustrate what the preferred output is, consider the following table, with associated value progress to count the number of times Mathematica loops through the table body.

progress = 0;
Y = 40;
Do[Table[progress += 1;, {l\[LetterSpace]1, l\[LetterSpace]0 + 1, 
    Y}], {l\[LetterSpace]0, Range[Y]}];
Print@progress

with result 780, and it appears that each iterator can be accessed inside the innermost body (required for my use case, and not shown here explicitly).

Here is also the case for one level of nesting deeper:

progress = 0;
Do[
 Table[
  progress += 1;
  , {l\[LetterSpace]1, 
   l\[LetterSpace]0 + 1, Y}, {l\[LetterSpace]2, 
   l\[LetterSpace]1 + 1, Y}]
 , {l\[LetterSpace]0, Range[Y]}] 
Print@progress

The result here is 9880 for the value of progress.

The idea is to reproduce the above functionality automatically, by only specifying the depth of the nesting X and of course the upper bound Y.

What follows are two non-working examples. The first idea is to simply feed the iterators remotely by some replacement rule. But no dice: the Table won't accept a List, which is what helperlist outputs. So for example:

progress = 0;
Do[
   Table[
    progress += 1;
    , helperlist]
   , {l\[LetterSpace]0, Range[Y]}]  /. 
 helperlist -> {{l\[LetterSpace]1, l\[LetterSpace]0 + 1, 
    Y}, {l\[LetterSpace]2, l\[LetterSpace]1 + 1, Y}}
Print@progress

One would expect a combination of Flatten[#,1] or some related function to massage this helperlist into something that could be fed to Table, but I have unfortunately not found anything that worked.

The closest to the desired output is in fact not achieved through Table, but by Folding Do:

progress = 0;
X = 2;
Y = 40;
helperlist := 
  Reverse[{ToExpression["l\[LetterSpace]" <> ToString[#]], 
      ToExpression["l\[LetterSpace]" <> ToString[# - 1]] + 1, Y} & /@ 
    Range[X]];
Quiet@Do[Fold[Do, Unevaluated[progress++], 
   helperlist], {l\[LetterSpace]0, Range[Y]}];
Print@progress

But using Quiet is not considered good coding, and neither is using so many Do loops, for that matter.

--

The "dream" is that the above variable number iterators can be fulfilled as a second argument to Table. Something along the lines of:

progress = 0;
X = 2;
Y = 40;
helperlist := {ToExpression["l\[LetterSpace]" <> ToString[#]], 
     ToExpression["l\[LetterSpace]" <> ToString[# - 1]] + 1, Y} & /@ 
   Range[X];
Do[
  Table[
   progress += 1;
   , helperlist]
  , {l\[LetterSpace]0, Range[Y]}];
Print@progress
$\endgroup$
0
$\begingroup$

Subset iterator

Maybe you could do something like:

X = 3;
Y = 5;
Table[l[i] = Indexed[g, i], {i, X}];
Table[{l[1], l[3]}, {g, Subsets[Range[Y],{X}]}]

{{1, 3}, {1, 4}, {1, 5}, {1, 4}, {1, 5}, {1, 5}, {2, 4}, {2, 5}, {2, 5}, {3, 5}}

You could create a function to do this:

SetAttributes[iteratedTable,HoldAll]

iteratedTable[e_, g_Symbol, iterations_, max_] := Block[{g = Indexed[\[FormalL], #]&},
    Table[e, {\[FormalL], Subsets[Range@max, {iterations}]}]
]

Simple example:

iteratedTable[h[l[1], l[3], l[2]], l, 3, 5]

{h[1, 3, 2], h[1, 4, 2], h[1, 5, 2], h[1, 4, 3], h[1, 5, 3], h[1, 5, 4], h[2, 4, 3], h[2, 5, 3], h[2, 5, 4], h[3, 5, 4]}

Your examples:

progress = 0;
iteratedTable[progress++, l, 2, 40];
progress

780

and:

progress = 0;
iteratedTable[progress++, l, 3, 40];
progress

9880

Nested iterators

An alternate approach that is similar to yours is:

SetAttributes[iteratedTable, HoldAll]
iteratedTable[e_, g_, iter_, max_] := ReleaseHold @ Hold[Table][
    Hold[e],
    Sequence @@ Table[{g[i], If[i==1, 1, g[i-1]+1], max}, {i, iter}]
]

Avoiding indexed variables

If you must have symbols instead of indexed variables, I think you should give the function the list of symbols. So:

SetAttributes[iteratedTable,HoldAll]

iteratedTable[e_, g:{__Symbol}, max_] := Block[g, 
    g = Thread[Indexed[\[FormalL], Range@Length@g]];
    Table[e, {\[FormalL], Subsets[Range@max, {Length@g}]}]
]

Examples:

iteratedTable[h[a,c], {a,b,c}, 5]

{h[1, 3], h[1, 4], h[1, 5], h[1, 4], h[1, 5], h[1, 5], h[2, 4], h[2, 5], h[2, 5], h[3, 5]}

progress=0;
iteratedTable[progress++, {l1, l2, l3}, 40];
progress

9880

$\endgroup$
  • $\begingroup$ For those who want to keep the Letterspace'd variables: ClearAll["g"]; X = 1; Y = 50; Table[With[{lhs = ToExpression["l\[LetterSpace]" <> ToString[i]]}, lhs = Indexed[g, i]], {i, X}]; Table[{l\[LetterSpace]1}, {g, Subsets[Range[Y], {X}]}] $\endgroup$ – user63309 May 2 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy