In the documentation for the Do[...] function, a loop of nesting up to any number of layers is supported. But to apply their function, one needs to know ahead of time how many layers of loops they're using. Is it possible to encode a nested loop where the number of layers is arbitrary?
For example, I want to do something like the following
Do[ (*tasks*),{v1, iters1}, {v2, iters2}] ...,, {vN, itersN} ]
where 'iters2' depends on $(v_1 \in \text{iters1})$, 'iters3' depends on both $(v_1 \in \text{iters1},v_2 \in \text{iters2})$, and so on up to 'itersN' that depends on all the $(v_1,\dots,v_{N-1})$. In particular, I want to do this where I don't know what $N$ is.
I can do this somewhat painstakingly by carefully keeping track of all the iterators and loop variables and carefully implementing counting. But it would be much nicer if this was possible natively. I tried using the apply '@@' function, but
Do@@{(*tasks*),{{v1,iters1},{v2,iters2},...,{vN,itersN}}}
doesn't work. E.g.
Do @@ {Print[i];, {i, 1, 5}}
simply prints the unassigned variable 'i'. Is there some short way to do what I'm asking?
Maybe an answer could illustrate this for all lists of $n$ ascending positive integers less than or equal to $2 n$, which is schematically
Do[Print[{i[1],...,i[N]}],{{v[1],1,2 n},{v[2],v[1]+1,2 n},...,{v[n],v[n-1]+1,2 n}}]
While I thought earlier that the listed comments/answers are sufficient, it turns out they're actually not useful for the case I'm interested in. Let's consider the following 'coloring' problem which is closer in flavor to what I want. (I changed the game slightly to be closer in flavor to the problem I'm having)
Color the integers $\{1,\dots,n\}$ as $\{c(1),...,c(n)\}$ which are one of four colors $c(i) \in \{\text{Red,Blue,Green,Black}\}$ with the following rules:
- '1' and '2' can be colored anything you want
- Given colorings on $(j-1,j-2)$, we are allowed to color '$j$' as any color that isn't $c(j-1)$ or $c(j-2)$. We can write this as $c(j) \in \ell(c(j-1)) \cap \ell(c(j-2))$, where $\ell(\text{color})=\{\text{Red,Blue,Green,Black}\} \backslash \{\text{color}\}$
Number the colors as $\text{Red}\to 1$,$\text{Blue}\to 2$,$\text{Green}\to 3$,$\text{Black}\to 4$. And call $v[j] \in \{1,2,3,4\}, j \in \{1,\dots,n\}$ a possible vector of colors if
MemberQ[Intersection[nextList[[v[j-1]]],nextList[[v[j-2]]]],v[j]]
where
nextList = {{2,3,4},{1,3,4},{1,2,4},{2,3,4}}
The problem with the listed answers is that there are errors when calling elements of a Table. However, following J.M.ennui's answer in the comments
nextList = {{2, 3, 4}, {1, 3, 4}, {1, 2, 4}, {1, 2, 3}};
n = 3;
Do[Table[v[i], {i, n}] // Print;, ##] & @@
Table[{v[j],
If[j == 1 || j == 2, {1, 2, 3, 4},
Intersection[Indexed[nextList, v[j - 1]],Indexed[nextList, v[j - 2]]]]}, {j, n}]
doesn't work (although the n=2
case works just fine). Nor does Bob Hanlon's answer work, or replacing each v[j]
with Subscript[v,j]
. But, the answers provided do work when I consider a different problem that doesn't involve the Intersection
function. Is there a syntax that supports this more general question?
The errors that show up are:
Indexed::argr: Indexed called with 1 argument; 2 arguments are expected.
Do::iterb: Iterator {Subscript[v, 3],Indexed[{{2,3,4},{1,3,4},{1,2,4},{1,2,3}}]} does not have appropriate bounds.
Do[(* stuff *), ##] & @@ Table[{K[j], 1, n}, {j, 5}]
orDo[(* stuff *), ##] & @@ Prepend[Table[{K[j], 1, K[j + 1]}, {j, 4, 1, -1}], {K[5], 1, n}]
a lot of times before. An acceptable alternative is to use e.g.IntegerPartitions[]
orTuples[]
to generate the indices, and loop over those. $\endgroup$nextList[[v[j - 1]]]
withIndexed[nextList, v[j - 1]]
? $\endgroup$