# Scramble matrix under some condition

Assume I have a matrix.

(mat = Partition[Range@9, 3]) // MatrixForm


mat$=\left( \begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}\right)$

I would like to scramble matrix matcolunmn-wise to generate all possible new matrix newMat under some condition.

Conditions are:

1) Column elements of mat must stay in their column, i.e. 1st column of newMat must be one of the elements of the Permutations[{1, 4, 7}, {3}]={{1, 4, 7}, {1, 7, 4}, {4, 1, 7}, {4, 7, 1}, {7, 1, 4}, {7, 4, 1}}; And similarly col2 $\in$ Permutations[{2,5,8}, {3}] and col3 $\in$ Permutations[{3,6,9}, {3}].

2) 1st row of mat is {1,2,3} and thus 1st Row entries of newMat, should not contain any of element of this set= {{1, 2}, {1, 3}, {2, 3},{1,2,3}} i.e. pairs or triple. The same for row 2 and row 3.

Some of the undesired newMat: It passes first condition but not second condition. For $3\times3$ there are only 3!2!1!= 12 matrices satisfies the condition which shows below. For $4\times4$ there are only 4!3!2!1!= 288 Good candidate:

newMat$=\left( \begin{array}{ccc} 1 & 8 & 6 \\ 4 & 2 & 9 \\ 7 & 5 & 3 \\ \end{array} \right)$

I would like to generate all $4\times4$ square matrices and if possible/easy all $5\times4$ matrices (there are 5!4!3!2!=34560). Any suggestion.

Edit

After I used @yohbs code I was able to generate all desired matrices but it is not efficient for $4\times4$ matrices.

sub = Join @@ (Subsets[#, {2}] & /@ mat);

Extract[allScrambles,
Position[Table[
Count[Flatten@
Table[ContainsAll[#, sub[[i]]] & /@ allScrambles[[j]], {i,
Length@sub}], False], {j, Length@allScrambles}], r^r]] • I can't understand the question. What is "they" in condition (1)? Condition (2) isn't even grammatically correct. If you use clear phrasing and reduce the amount of effort people need to make to understand what you want, you will get better answers. – Szabolcs Apr 12 '18 at 10:35
• @Szabolcs sorry for ambiguity. See my edit. – OkkesDulgerci Apr 12 '18 at 13:22
• Thanks, it's much clearer now. – Szabolcs Apr 12 '18 at 14:26
• Does condition (2) mean the row should not contain any sequence of those numbers? – Awkward Panda May 12 '18 at 16:28
• Yes that's right – OkkesDulgerci May 12 '18 at 16:55

If your matrix is mat then this generates all scrambles of columns:

{r, c} = Dimensions[mat]
perms = Permutations[Range@r];
q = 1 + IntegerDigits[Range[(r!)^ c], r!, c];
allScrambles =
Transpose[
Table[mat[[perms[[q[[i, j]]]], j]], {j, c}, {i, Length@q}],
{3, 1, 2}];


Then you can check whether a scrambled matrix has a row in common with the original one:

check[candidate_, original_] :=  Not[Or @@ (MemberQ[original, #] & /@ candidate)]


and use that to filter out:

result = Select[allMatrices, check[#, mat] &];


for mat=Partition[Range@12, 4] these are the first 16 results: You can probably optimize in terms of running time, but for these small sizes it's so fast already that there's no need to. Also, if you want a random scramble without generating them all you can simply do

scramble[matrix_]:=Transpose@Table[RandomSample@col, {col, Transpose@matrix}]

• It does not produce desired output. Can you please check it. BTW what is allMatrices? – OkkesDulgerci Apr 10 '18 at 23:52
• allScrambles is right. But check is not right. If I am right, it should produce 3!2!1!=12 matrices. What I want is 1,2,3 should bot in be in the same row. Similarly, 4,5,6 and 7,8,9 should not be in the same row. – OkkesDulgerci Apr 11 '18 at 0:20
• I can't quite understand what you mean be "4,5,6" should not be in the same row". Any two cannot be? all three? It would be helpful if you could supply the full list of permissible matrices for some small example – yohbs Apr 11 '18 at 20:00

Apologies for the faux pas of a clumsy answer but I have an attempt:

Given your initial matrix and list

(m0 = Partition[Range@9, 3]) // MatrixForm

&

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

Finding all column permutations for condition (1)

m1=Permutations[Transpose[m0][[#]]]&/@Range@3


Then taking permutations (one from each list using Tuples)

m2 = Transpose[#] & /@ Tuples[m1]//Dimensions
Out= {216,3,3}


Had a little trouble with the second condition, not sure this is right but...

Pick[m2, IntersectingQ[m2[[#]], s] & /@ Range@Length[m2],False]


But this gives 156 matrices rather than OP's predicted 12

If terribly wrong, please delete. Thanks.

EDIT*

Realised it is not taking out any of the 2 number sublists of s