-6

I have a variable called sukokus which is a 9x9x50 array, and it represents the solutions to 50 different sudoku puzzles, some of hwich are right some of which are wrong. How can I use simple indexing to check for the correct solutions?

eagles02
  • 65
  • 6
  • 5
    Wanted to give you feedback on why this question is getting downvotes. It is generally frowned upon to request that others give you code to solve a problem for you, especially if you don't show that you have made any effort towards solving the problem yourself. Additionally, you should provide those who would help you with example data, so that they can easily help you. See http://stackoverflow.com/questions/how-to-ask http://stackoverflow.com/help/how-to-ask and http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example to see how to ask questions on this site – Jota Feb 11 '14 at 01:47
  • Thank you for the explanation. Will not happen again. – eagles02 Feb 11 '14 at 02:45

2 Answers2

11

Here is one. It uses the interesting property found here: 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
}

Quick check that it works. Here is a good solution:

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)

and a bad one:

s2 <- s1
s2[1:2] <- s2[2:1]

Then indeed:

check.solutions(array(c(s1, s2), c(9,9,2)))
# [1]  TRUE FALSE
Community
  • 1
  • 1
flodel
  • 87,577
  • 21
  • 185
  • 223
2

Maybe not efficient, but it shows a way to check for rows, columns, and 3*3-boxes by simple indexing:

# 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])
})
lukeA
  • 53,097
  • 5
  • 97
  • 100