我有一个包含二进制向量行的矩阵:
library(gtools)
mat<-permutations(2,6,v=c(0,1),repeats.allowed=TRUE)
我想对矩阵的行进行排序,以使每行与其直接邻居(上方和下方)相差1位。
这可能吗?
答案 0 :(得分:5)
有趣的问题!我想要实现这一目标的方法是从具有较少位数的那些矩阵中递归地构建这样的矩阵。假设我们有一个n位矩阵(包含所有2 ^ n个唯一的n位序列),其中每个邻居最多相差一个。如果我们rbind
这个矩阵的反转(按行),那么结果的每一行最多相差1,中间的两行将是相同的。我们可以在前半部分前面添加0,在后半部分前面添加1。结果包含所有2 ^(n + 1)个唯一(n + 1)位序列,所有邻居的距离最多为1。
对于基本情况,我们可以使用(0 1)表示1位矩阵。
get.mat <- function(size) {
if (size == 1) {
return(matrix(c(0, 1), ncol=1))
} else {
smaller <- get.mat(size-1)
return(rbind(cbind(0, smaller), cbind(1, smaller[nrow(smaller):1,])))
}
}
get.mat(4)
# [1,] 0 0 0 0
# [2,] 0 0 0 1
# [3,] 0 0 1 1
# [4,] 0 0 1 0
# [5,] 0 1 1 0
# [6,] 0 1 1 1
# [7,] 0 1 0 1
# [8,] 0 1 0 0
# [9,] 1 1 0 0
# [10,] 1 1 0 1
# [11,] 1 1 1 1
# [12,] 1 1 1 0
# [13,] 1 0 1 0
# [14,] 1 0 1 1
# [15,] 1 0 0 1
# [16,] 1 0 0 0
构建这些矩阵的方法的一个有趣的副作用是第一行和最后一行的距离也相互为止。
答案 1 :(得分:2)
这是另一种递归方法,感谢@josilber的想法。
# calculates the decimal difference between adjacent (1 digit difference)
# binary digits of length n, starting with 2.
diffs <- function(n) {
if (n == 1) {
return(n)
} else {
k <- Recall(n - 1)
c(k, 2^(n-1), rev(-k))
}
}
get.mat2 <- function(ncols) {
adj.ints <- rev(cumsum(c(0, diffs(ncols)))) # get all differences
mat32 <- matrix(rev(as.integer(intToBits(adj.ints))), ncol=32, byrow=TRUE) # convert to binary representation in matrix
mat32[, (33-ncols):32] # remove extraneous columns
}
如果您将行视为十进制整数,我很好奇图案是什么:
m <- get.mat(8)
ints <- strtoi(apply(m, 1, paste, collapse=''), 2)
plot(ints, type='b')
这显然是一种模式。它看起来非常稳定&#34;所以我采取了第一个区别:
diffs <- diff(strtoi(apply(m, 1, paste, collapse=''), 2))
plot(diffs, type='b')
在检查此图表几n后,上面的算法跳出来了。作为次要说明,这种方法似乎没有明显更快:
ncols <- 20
system.time(josilber <- get.mat(ncols))
# user system elapsed
# 1.90 0.13 2.05
system.time(plourde <- get.mat2(ncols))
# user system elapsed
# 1.61 0.19 1.81
josilber <- matrix(as.integer(josilber), ncol=ncol(josilber))
identical(josilber, plourde)
# TRUE