这是一个非常快的基本 R 解决方案:
Joseph <- function(m, p) {
mat <- matrix(0L, nrow = m, ncol = m*p)
for (i in 1:m) {mat[i, p*(i-1L) + 1:p] <- 1L}
mat
}
以下是一些相等比较:
fun989 <- function(m, p){
a <- diag(m)
a[,rep(seq_len(m), each=p)]
}
IMO <- function(m, p) {
myMat <- matrix(0L, m, m*p)
myMat[cbind(rep(seq_len(nrow(myMat)), each=p), seq_len(ncol(myMat)))] <- 1
myMat
}
JOGO <- function(m, p) {matrix(rep(diag(m), each = p), nrow = m, byrow = TRUE)}
APOM <- function(m, p) {t(apply(diag(m), 2, rep, each = p))}
library(compiler)
enableJIT(3) ## compiling each function
all.equal(Joseph(100, 50), fun989(100, 50))
[1] TRUE
all.equal(Joseph(100, 50), APOM(100, 50))
[1] TRUE
all.equal(Joseph(100, 50), JOGO(100, 50))
[1] TRUE
all.equal(Joseph(100, 50), IMO(100, 50))
[1] TRUE
enableJIT(0) ## return to standard setting
以下是基准:
library(microbenchmark)
microbenchmark(Joseph(100, 50), JOGO(100, 50), fun989(100, 50), APOM(100, 50), IMO(100, 50), unit = "relative")
Unit: relative
expr min lq mean median uq max neval cld
Joseph(100, 50) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100 a
JOGO(100, 50) 33.388929 20.892988 6.593804 22.365625 19.161056 1.167957 100 b
fun989(100, 50) 7.192071 4.577225 2.044973 4.432824 4.129563 1.029050 100 a
APOM(100, 50) 40.244128 28.176729 8.805715 27.785985 23.966477 1.209582 100 b
IMO(100, 50) 6.119685 3.898451 2.712222 6.192030 6.033916 1.044422 100 a