Loop with variable nesting depth and variable count at each level

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
5 replies · 3K views
Swamp Thing
Insights Author
Messages
1,062
Reaction score
819
TL;DR
"M" levels of nested loops;
each loop running from 1 to Counts[[m]]
In Mathematica, how can we have "M" levels of nested loops, with each loop (level) going from 1 to Counts=##\{N_1, N_2, ... N_M\}## respectively, where the value of M and the elements of Counts are computed beforehand?
 
Physics news on Phys.org
Swamp Thing said:
TL;DR Summary: "M" levels of nested loops;
each loop running from 1 to Counts[[m]]

In Mathematica, how can we have "M" levels of nested loops, with each loop (level) going from 1 to Counts=##\{N_1, N_2, ... N_M\}## respectively, where the value of M and the elements of Counts are computed beforehand?

Do a single loop of length [itex]N_1N_2 \dots N_M[/itex] and calculate the values of the separate indices [itex](i_1, \dots, i_M)[/itex] in each iteration based on the single index [tex] 1 \leq i = 1 + (i_1 - 1) + N_1(i_2 - 1) + N_1N_2(i_3 - 1) + \dots + (N_1N_2 \cdots N_{M-1})(i_M - 1) \leq (N_1 \cdots N_{M})[/tex] as [tex] \begin{split}<br /> i_1 &= 1 + (i \mod N_1) \\<br /> i_2 &= 1 + ((i - i_1)/N_1 \mod N_2) \\<br /> i_3 &= 1 + ((i - i_1 - N_1i_2)/N_2 \mod N_3)<br /> \end{split}[/tex] etc.

EDIT: More efficient is to increment [itex]i_1[/itex] after each loop, and increment [itex]i_2[/itex] and reset [itex]i_1[/itex] if this makes [itex]i_1 > N_1[/itex], etc.
 
Last edited:
jedishrfu said:
There is a discussion on stackexchange about using recursion
pasmith said:
Do a single loop of length N1N2…NM and calculate the values of the separate indices

Thanks, I will do both methods as an exercise to keep from getting rusty. I have always felt a bit daunted by recursive code, so this may be a good time to lay that to rest. And pasmith's method seems to have a lot of moving parts, which will be interesting to master.
 
Code:
// Initialize loop counters
for i = 1 to M:
   I[i] = 1

while true:

    // do stuff

   // Increment I[1]
   I[1] += 1

   for i = 1  to M-1:
      // If I[i] has advanced beyond Counts[i], set it to 1 and increment I[i+1].
      if I[i] > Counts[i]:
         I[i] = 1
         I[i+1] += 1

   // As soon as I[M] is out of range we are done.
   if I[M] > Counts[M]:
      break
 
Reply
  • Like
Likes   Reactions: Swamp Thing
Here's am example of factorial in Mathematica from the RosettaCode site:

Mathematica / Wolfram Language

Note that Mathematica already comes with a factorial function, which can be used as e.g. 5! (gives 120). So the following implementations are only of pedagogical value.

Recursive​

Code:
factorial[n_Integer] := n*factorial[n-1]
factorial[0] = 1

Iterative (direct loop)​

Code:
factorial[n_Integer] :=
  Block[{i, result = 1}, For[i = 1, i <= n, ++i, result *= i]; result]

Iterative (list)​

Code:
factorial[n_Integer] := Block[{i}, Times @@ Table[i, {i, n}]]

https://rosettacode.org/wiki/Factorial#Mathematica_/_Wolfram_Language

and more languages implementing factorial:

https://rosettacode.org/wiki/Factorial

I like this site because of its numerous examples and language comparisons.

With respect to recursion, the recursing method has a conditional that stops the recursion at the start of the method, which is best illustrated in Python:

Recursive
Python:
def factorial(n):

    if n<1:      ## stops recursion and blocks negative n values
        return 1

    return n*factorial(n-1)
 
Last edited:
Reply
  • Like
Likes   Reactions: Swamp Thing