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. enter image description here

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]]

enter image description here

  • 1
    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 at 10:35
  • @Szabolcs sorry for ambiguity. See my edit. – Okkes Dulgerci Apr 12 at 13:22
  • Thanks, it's much clearer now. – Szabolcs Apr 12 at 14:26
  • Does condition (2) mean the row should not contain any sequence of those numbers? – Awkward Panda May 12 at 16:28
  • Yes that's right – Okkes Dulgerci May 12 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:

enter image description here

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? – Okkes Dulgerci Apr 10 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. – Okkes Dulgerci Apr 11 at 0:20
  • 2
    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 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[59]= {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

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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