问题
I´m facing a problem with constructing a randomised matrix where I partially already have values (that need to stay fixed - so no further randomisation there).
Lets see:
matrix should end up being 10 by 10
n <- 10
I do want my first rows to be the data I enter. e.g:
row1<- c(1,4,7,6,5,3,2,8,9,10)
row2<- c(10,7,3,2,1,4,5,9,8,6)
row3<- c(9,2,4,3,8,7,10,1,6,5)
To bild a matrix with 10 rows (and 10 columns) I combined those rows with samples (no replace because I want each number to be unique in each row).
first.rows<-rbind(row1,row2,row3,sample(n,n,replace=F),sample(n,n,replace=F),sample(n,n,replace=F),sample(n,n,replace=F),sample(n,n,replace=F),sample(n,n,replace=F),sample(n,n,replace=F))
output:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
row1 1 4 7 6 5 3 2 8 9 10
row2 10 7 3 2 1 4 5 9 8 6
row3 9 2 4 3 8 7 10 1 6 5
6 1 5 4 2 10 3 8 7 9
2 5 7 8 9 6 1 3 4 10
10 6 4 1 8 3 7 2 5 9
8 5 3 2 4 1 10 7 6 9
10 7 9 6 8 2 5 4 3 1
1 10 8 4 7 3 5 2 6 9
2 1 10 4 8 9 3 6 5 7
So far so good.. However now I have the problem that there is no control for unique numbers in the columns. This is what I would need though. I get that this the case because I used rbind (and therefore only the function of no duplicates only works for the rows). But I do not know how else to approach this problem. The rows 1-3 should stay exactly as they are now.
Any ideas?
回答1:
I think my previous solution Fixed values not repeated over column and row can be modified to work. You need a solver, but instead of starting with a empty grid, it starts with a pre-filled matrix:
# x is your matrix, "not filled" values should be NA
# x is a square matrix with dimension n (big n will take longer to converge)
backtrack = function(x){
n = ncol(x)
stopifnot(ncol(x)==nrow(x))
cells = list()
k = 1
for (i in 1:n){
for (j in 1:n){
if (is.na(x[i, j]))
cells[[k]] = sample(1:n)
else
cells[[k]] = NULL
k = k + 1
}
}
i = 0
while (i < n*n){
if (is.null(cells[[i+1]])){
i=i+1
next
}
candidates = cells[[i + 1]]
idx = sample(1:length(candidates), 1)
val = candidates[idx]
if (length(candidates) == 0){
cells[[i + 1]] = sample(1:n)
i = i - 1
x[as.integer(i/n) + 1, i %% n + 1] = NA
}
else {
rr = as.integer(i/n) + 1
cc = i %% n + 1
if ((val %in% x[rr, ]) || (val %in% x[, cc])){
candidates = candidates[-idx]
cells[[i + 1]] = candidates
}
else{
x[as.integer(i/n) + 1, i %% n + 1] = val
candidates = candidates[-idx]
cells[[i + 1]] = candidates
i = i + 1
}
}
}
x
}
Empty initial matrix
set.seed(1)
x = backtrack(matrix(NA, nrow = 10, ncol = 10))
print(x)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 8 10 4 6 9 7 1 2 3 5
[2,] 5 6 9 8 1 10 4 3 2 7
[3,] 10 7 1 2 8 9 5 4 6 3
[4,] 3 9 8 10 6 5 7 1 4 2
[5,] 9 1 6 4 7 3 2 5 10 8
[6,] 1 4 10 3 2 6 8 7 5 9
[7,] 2 8 5 9 10 1 3 6 7 4
[8,] 6 5 2 7 3 4 10 9 8 1
[9,] 4 3 7 1 5 2 6 8 9 10
[10,] 7 2 3 5 4 8 9 10 1 6
Pre-filled initial matrix
m = matrix(NA, ncol = 10, nrow = 10)
m[1, ] = c(1,4,7,6,5,3,2,8,9,10)
m[2, ] = c(10,7,3,2,1,4,5,9,8,6)
m[3, ] = c(9,2,4,3,8,7,10,1,6,5)
x = backtrack(m)
print(x)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 4 7 6 5 3 2 8 9 10
[2,] 10 7 3 2 1 4 5 9 8 6
[3,] 9 2 4 3 8 7 10 1 6 5
[4,] 5 9 6 8 3 2 4 7 10 1
[5,] 7 1 5 10 9 6 3 2 4 8
[6,] 2 5 8 1 10 9 6 3 7 4
[7,] 6 3 1 4 7 5 8 10 2 9
[8,] 8 10 9 5 4 1 7 6 3 2
[9,] 3 6 10 9 2 8 1 4 5 7
[10,] 4 8 2 7 6 10 9 5 1 3
NOTE: I didn't tested it for bugs.
来源:https://stackoverflow.com/questions/46186549/constructing-a-randomised-matrix-with-no-duplicates-but-fixed-partial-input