Generating a family of 0-1 matrices satisfying a particular property

I'm looking for an elegant way to generate the set of all possible matrices that satisfy the following properties:

1. Each matrix has 9 rows and c columns, where 1<=c<=9.
2. Each matrix has exactly one 1 in each row. All other entries in that row are zero.

At one extreme is the identity matrix,

S=IdentityMatrix

At the other extreme is the vector of all ones,

S = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};

One of the 9-by-3 matrices takes the form,

S = {{1, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0, 1}, {0, 1, 0}, {0, 0, 1}};

...and so on.

• I would do this: Fix the number of columns at $k$. Consider each row to be a base-$k$ digit. Use IntegerDigit to express all integers up to $k^9$ in base-$k$. Convert those digits to the 0-1 vectors you want. Apr 2 '17 at 20:40
• @Szabolcs: Sounds like you're saying something like the following: k=4; Do[ v=IntegerDigits[j,k] ???? {j,1,k^9}] I'm not sure exactly what you mean at ???. Sorry if the formatting of this response does not appear the way it should. Apr 2 '17 at 21:31

We can generate all of the matrices for a given $c$ like this:

matrices[c_] := Map[UnitVector[c , #] &, Tuples[Range[c], 9], {2}]

We can use this, for example, to generate the 19,683 ($3^9$) matrices for $c = 3$. We will only look at four representative samples:

$c3 = matrices;$c3[[{1, 7328, 14932, 3^9}]] // Map[MatrixForm] // Row This works for small $c$, but when $c = 9$ there are $9^9 = 387,420,489$ matrices. This will probably not fit into memory. If all we need is the ability to generate a random matrix that meets the requirements, then:

randomMatrix[c_] := UnitVector[c, #] & /@ RandomInteger[{1, c}, 9]

randomMatrix // MatrixForm However, if we wish to be more systematic, then we need a function that will only return a particular matrix $n$, where $1 \le n \le c^9$:

matrix[c_, n_] := UnitVector[c, #] & /@ (1 + IntegerDigits[n - 1, c, 9])

We could iterate over all $n$ if we wish... or extract particular ones that might interest us without generating the rest:

matrix[9, #] & /@ {1, 8797232, 287348282, 9^9} // Map[MatrixForm] // Row • Blast, I just spent ten minutes writing this exact code! (matrices.) I really need to read other answers first. Apr 3 '17 at 5:30
• An alternative: matrices[c_Integer?Positive] := SparseArray[Flatten[MapIndexed[Append[#2, #1] -> 1 &, Tuples[Range, 9], {2}]]]. Also: matrix[c_, n_] := IdentityMatrix[c][[1 + IntegerDigits[n - 1, c, 9]]]. Apr 3 '17 at 7:09

You can do:

parList[c_, nine_: 9] :=
Flatten[Apply[Outer, Prepend[ Array[Range[c] &, nine], List]],
nine - 1]

makeMat[l_, c_] := Table[If[i == #, 1, 0], {i, 1, c}] & /@ l

makeMat[#, c] & /@ parList[c, 9]

Where $c$ is your number of columns (unless I have misunderstood the question).

• Perfect! Thanks. Apr 2 '17 at 22:52
f[m_] := Tuples[IntegerDigits[#, 2, m] & /@ PowerRange[1,2^(m - 1), 2],9]

e.g.the 512 for c=2:

Grid[Partition[ArrayPlot[#, ImageSize -> 10] & /@ f, 32]] Generate positions and insert into a matrix of zeros

genMatrix[rows_Integer?Positive, cols_Integer?Positive] :=
Insert[ConstantArray[0, {rows, cols - 1}], 1,
Transpose@{Range[rows], RandomInteger[{1, cols}, rows]}]

Then

genMatrix[9, 4] // MatrixForm @Szabolcs Generate base-2 digits (see OP comments)

genMatrix2[rows_Integer?Positive, cols_Integer?Positive] :=
PadLeft[IntegerDigits[RandomChoice[2^# & /@ Range[0, cols - 1], rows], 2], {rows, cols}]

Then

genMatrix2[9, 4] // MatrixForm Hope this helps.