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
  • 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$ May 1, 2018 at 21:26

1 Answer 1

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$
1
  • 2
    $\begingroup$ Even so, you're probably better of using Do or Table instead of For. $\endgroup$ May 1, 2018 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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