2
$\begingroup$

Writing:

Tuples[{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}]

I get:

{{1, 4, 7}, {1, 4, 8}, {1, 4, 9}, {1, 5, 7}, {1, 5, 8}, {1, 5, 9}, {1,6, 7},
 {1, 6, 8}, {1, 6, 9}, {2, 4, 7}, {2, 4, 8}, {2, 4, 9}, {2, 5, 7}, {2,5, 8},
 {2, 5, 9}, {2, 6, 7}, {2, 6, 8}, {2, 6, 9}, {3, 4, 7}, {3, 4, 8}, {3,4, 9},
 {3, 5, 7}, {3, 5, 8}, {3, 5, 9}, {3, 6, 7}, {3, 6, 8}, {3, 6, 9}}

Similarly, by defining the function:

tuples[matrix_] := Module[{A, i, h, j, k, m, n},
  {m, n} = {Length[matrix], Length[Transpose[matrix]]};
  A = ConstantArray[0, {n^m, m}];
  h = 0; k = 1;
  For[j = 1, j <= m, j++,
      h = h + 1;
      For[i = 1, i <= n^m, i++,
          A = ReplacePart[A, {i, j} -> matrix[[h]][[k]]];
          If[Mod[i, n^m/n^h] == 0, k = k + 1];
          If[k > n, k = 1]
] ]; Return[A]]

and writing:

tuples[{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}]

I get:

{{1, 4, 7}, {1, 4, 8}, {1, 4, 9}, {1, 5, 7}, {1, 5, 8}, {1, 5, 9}, {1,6, 7},
 {1, 6, 8}, {1, 6, 9}, {2, 4, 7}, {2, 4, 8}, {2, 4, 9}, {2, 5, 7}, {2,5, 8},
 {2, 5, 9}, {2, 6, 7}, {2, 6, 8}, {2, 6, 9}, {3, 4, 7}, {3, 4, 8}, {3,4, 9},
 {3, 5, 7}, {3, 5, 8}, {3, 5, 9}, {3, 6, 7}, {3, 6, 8}, {3, 6, 9}}

But if I write now:

Tuples[{{1, 2, 3, 4}, {5, 6}, {7, 8, 9}}]

I get:

{{1, 5, 7}, {1, 5, 8}, {1, 5, 9}, {1, 6, 7}, {1, 6, 8}, {1, 6, 9},
 {2, 5, 7}, {2, 5, 8}, {2, 5, 9}, {2, 6, 7}, {2, 6, 8}, {2, 6, 9},
 {3, 5, 7}, {3, 5, 8}, {3, 5, 9}, {3, 6, 7}, {3, 6, 8}, {3, 6, 9},
 {4, 5, 7}, {4, 5, 8}, {4, 5, 9}, {4, 6, 7}, {4, 6, 8}, {4, 6, 9}}

and defining the function:

tuples[matrix_] := Module[{A, i, h, j, k, m, n},
  m = Length[matrix];
  n = 1; For[i = 1, i <= m, i++, n = n Length[matrix[[i]]]];
  A = ConstantArray[0, {n, m}];
  h = 0; k = 1;
  For[j = 1, j <= m, j++,
      h = h + 1;
      For[i = 1, i <= n, i++,
          A = ReplacePart[A, {i, j} -> matrix[[h]][[k]]];
          If[Mod[i, m / h] == 0, k = k + 1];
          If[k > Length[matrix[[j]]], k = 1]
] ]; Return[A]]

and writing:

tuples[{{1, 2, 3, 4}, {5, 6}, {7, 8, 9}}]

I get:

{{1, 5, 7}, {1, 5, 8}, {1, 5, 9}, {2, 6, 7}, {2, 6, 8}, {2, 6, 9},
 {3,5, 7}, {3, 5, 8}, {3, 5, 9}, {4, 6, 7}, {4, 6, 8}, {4, 6, 9}, 
{1, 5, 7}, {1, 5, 8}, {1, 5, 9}, {2, 6, 7}, {2, 6, 8}, {2, 6, 9}, 
{3, 5,7}, {3, 5, 8}, {3, 5, 9}, {4, 6, 7}, {4, 6, 8}, {4, 6, 9}}

which does not match with the output of MMA.

Most likely the problem lies in mod(...) but I just can not figure out how to correct it.

$\endgroup$
  • 1
    $\begingroup$ Just a side remark: Make your code easier and more performant with A[[i,j]] = matrix[[h,k]]] instead of A = ReplacePart[A, {i, j} -> matrix[[h]][[k]]]. This way, the matrix A is not copied in each iteration. $\endgroup$ – Henrik Schumacher May 1 '18 at 21:26
4
$\begingroup$

Rather than use For loops, I suggest a route through Outer:

Clear[tuples]
tuples[list_] := 
 Outer[List, Sequence @@ list] // 
  ArrayReshape[#, Dimensions[#] /. {a__, b_} :> {Times[a], b}] &

Testing this:

data = {{1, 2, 3, 4}, {5, 6}, {7, 8, 9}};
tuples[data] == Tuples[data] 

(* Out: True *)
$\endgroup$
  • $\begingroup$ Thanks Marco, as always very kind! Unfortunately, I would need to use the for loops to be able to use the code externally to MMA. Thank you! $\endgroup$ – TeM May 1 '18 at 15:25
  • 2
    $\begingroup$ Even so, you're probably better of using Do or Table instead of For. $\endgroup$ – Sjoerd Smit May 1 '18 at 15:28

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.