将矩阵排列成唯一的行和列

时间:2016-11-22 09:14:29

标签: r matrix combinatorics

说我有一个矢量,

vec <- c(rep(1,4),rep(2,4),rep(3,4),rep(4,4),rep(5,4),rep(6,4),rep(7,4),rep(8,4),rep(9,4))

我安排了一个矩阵6x6。

mat <- matrix(vec,6,byrow=T)

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

我希望将这些数字改组,使得它们对于每一行和每列都是唯一的。或者换句话说,任何行或列中都不得有重复数字。

矢量的长度,矢量的元素,矩阵的行数和列数都是固定的。唯一可以改变的方面是数字的位置。

我如何计算解决这个问题?

以下是一个可能的正确结果(手动完成)。请注意,没有行或列有任何重复的数字。

res <- matrix(c(3,1,2,5,7,8,6,8,5,2,9,4,8,6,7,4,3,5,2,9,3,1,6,7,1,4,9,7,5,6,4,2,1,9,8,3),nrow=6,byrow=T)

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

table(res)

res
1 2 3 4 5 6 7 8 9 
4 4 4 4 4 4 4 4 4

1 个答案:

答案 0 :(得分:1)

首先,有一种更好的方法来获取矢量。这将减少打字并使您的代码更清晰:

vec <- rep(1:8, each=4)
mat <- matrix(vec, ncol=6, byrow=T)

接下来,请注意您要按行排序元素的唯一排序。也就是说,您需要元素的permutationsN元素的唯一排列数为N!。我们可以在R中计算出这个数字:

factorial(length(unique(vec)))
# [1] 40320

这比您需要的数字排序更多。 (看起来你只想要6.)假设你想绘制一些随机排序,让我们从可能的40320中抽取6个数字:

set.seed(3931)  # this makes the example exactly reproducible
rows <- sample.int(40320, 6)
rows
# [1] 36601 24136  5713 23405 25328 32973

从这里开始,为了获得实际的排列,我们将使用R中的permute库。由于排列总数很大,我们必须将maxperm参数设置为大于其默认值(9999,我收集):

library(permute)
out <- allPerms(unique(vec), control=how(maxperm=41000))[rows,]
out
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# [1,]    8    2    7    1    3    4    6    5
# [2,]    5    7    4    1    6    8    2    3
# [3,]    2    1    8    6    3    4    7    5
# [4,]    5    6    4    1    2    8    7    3
# [5,]    6    1    3    2    5    7    4    8
# [6,]    7    4    6    5    8    2    3    1

我对误读这个问题表示歉意。 N元素的排列数量仅为r时使用N!/r!。这是一个简单的计算:

factorial(length(unique(vec))) / factorial(length(unique(vec))-6)
# [1] 20160

我不清楚如何让allPerms()使用少于所有元素。这是一个简单的解决方案:

library(permute)
out <- allPerms(unique(vec), control=how(maxperm=41000))[rows,1:6]
out
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    8    2    7    1    3    4
# [2,]    5    7    4    1    6    8
# [3,]    2    1    8    6    3    4
# [4,]    5    6    4    1    2    8
# [5,]    6    1    3    2    5    7
# [6,]    7    4    6    5    8    2