我有一个名为sukokus的变量,它是一个9x9x50阵列,它代表了50种不同数独游戏的解决方案,其中一些是正确的,其中一些是错误的。如何使用简单的索引来检查正确的解决方案?
答案 0 :(得分:11)
这是一个。它使用了这里有趣的属性:https://math.stackexchange.com/a/157716
check.solutions <- function(solutions) {
board <- matrix(1:81, 9, 9)
row.idx <- row(board)
col.idx <- col(board)
squ.idx <- (row.idx - 1L) %/% 3L + 1L + 3L * (col.idx - 1L) %/% 3L
grp.mat <- t(cbind(sapply(1:9, `==`, row.idx),
sapply(1:9, `==`, col.idx),
sapply(1:9, `==`, squ.idx)))
flat.sol <- 2^(solutions - 1)
dim(flat.sol) <- c(81, dim(flat.sol)[3])
colSums(grp.mat %*% flat.sol == 511) == 27
}
快速检查它是否有效。这是一个很好的解决方案:
s1 <- matrix(c(9,4,6,1,7,3,8,2,5,
2,8,3,9,4,5,1,7,6,
5,7,1,8,2,6,9,4,3,
4,1,5,2,3,7,6,9,8,
8,3,9,4,6,1,7,5,2,
6,2,7,5,9,8,4,3,1,
3,6,4,7,1,2,5,8,9,
7,5,2,6,8,9,3,1,4,
1,9,8,3,5,4,2,6,7), 9, 9)
一个坏人:
s2 <- s1
s2[1:2] <- s2[2:1]
然后确实:
check.solutions(array(c(s1, s2), c(9,9,2)))
# [1] TRUE FALSE
答案 1 :(得分:2)
可能效率不高,但它显示了一种通过简单索引检查行,列和3 * 3框的方法:
# create example data
library(sudoku)
sudokus <- array(dim=c(9, 9, 50))
for (i in 1:50)
sudokus[,,i] <- generateSudoku(Nblank = sample(c(0,1), size=1, prob=c(.9, .1)))
# main function (FALSE if invalid, TRUE if solved)
boxes <- expand.grid(col=seq(1, 9, 3), row=seq(1, 9, 3))
isValidSudoku <- function(sud) {
checkVec <- function(v)
1:9 %in% v
all(sapply(as.data.frame(sud), checkVec)) &
all(sapply(as.data.frame(t(sud)), checkVec)) &
all(sapply(1:nrow(boxes), function(i) {
checkVec(sud[as.matrix(expand.grid(row=boxes$col[i]:(boxes$col[i]+2),
col=boxes$row[i]:(boxes$row[i]+2)))])
}))
}
# check example data
sapply(1:dim(sudokus)[3], function(i) {
isValidSudoku(sudokus[,,i])
})