我需要找到R中每一行和每一列唯一的所有可能的整数1-5的5x5矩阵(想象一个数独)。
在没有创建所有120C5矩阵然后找到合适的矩阵的情况下,是否存在任何有效的方法?
谢谢!
答案 0 :(得分:3)
正如我在上面的评论中所说,这种类型的矩阵称为Latin squares。
首先,我们already know有56个所谓的缩小的拉丁方和161280个所有大小为5的拉丁方。缩小的拉丁方使得第一列和第一行都只有1 ,2、3、4、5(按此顺序)。给定那些缩小的拉丁方格,只要容易(只要大小不大于5)就可以生成所有拉丁方格:排列除第一个以外的所有行,并排列所有列。因此,正如预期的那样,161280 = 5!* 4!* 56。
通过限制第一行和第一列,可以生成4!* 3!* 2!= 288个矩阵,并检查其中56个是拉丁方。但是,我将跳过该列表,并从here中获取他们的列表。
首先,我们读取并重新排列数据
reduced <- read.table("http://users.cecs.anu.edu.au/~bdm/data/reduced5.txt", head = FALSE, colClasses = "character")
reduced <- lapply(1:nrow(reduced), function(r) matrix(as.numeric(unlist(strsplit(unlist(reduced[r, ]), ""))) + 1, 5))
length(reduced)
# [1] 56
现在让我们生成所有5个!和4! 1,2,3,4,5和1,2,3,4的排列。
library(combinat)
perms5 <- permn(1:5)
perms4 <- permn(1:4)
最后,我们遍历所有缩小的拉丁方格并以各种可能的方式对其进行置换
allLS <- sapply(reduced, function(m) {
LS <- vector("list", gamma(6) * gamma(5))
for(i in 1:gamma(5))
for(j in 1:gamma(6))
LS[[(i - 1) * gamma(6) + j]] <- m[perms4[[i]] + 1, perms5[[j]]]
LS
})
只需几秒钟,我们便得到结果
length(allLS)
# [1] 161280
很容易验证它们是否都不同
table(table(sapply(allLS, paste0, collapse = "")))
# 1
# 161280
,您还可以检查它们是否均为拉丁方块。