rchessn-queenschessboard.js

R: N-Queens finding the Diagonal


Made a post earlier today expressing I was trying to find a solution to the N-Queens problem. The first part of this is determining the following function:

>safe(chess.piece,chess.board)

Where:

>chess.board <- matrix(0,8,8)
>chess.board[r,c] <- 1 #1 represents the queen which can be placed in any row/column on the board
>chess.piece <- c(x,x) #basically and row/column value I choose in the 8x8 matrix

Currently I have the following code for the horizontal and vertical planes:

>safe <- function(a,b){
  if((sum(b[a[1],])<1) & (sum(b[,a[2]])<1))
  {return(TRUE)
  }else{
    return(FALSE)
  }
}

Basically works on summing the rows/columns and checking if greater (FALSE) or equal (TRUE) to 0. But how in the world do I find the diagonal sum of the chess.board matrix based on the rows/columns determined by the chess.piece ?! I am ripping my hair out over this as I am decently new to R but I need a solution and just can't seem to figure it out.

Any help would be greatly appreciated! Thanks in advance, J.S


Solution

  • One approach is to write a couple of functions to extract partial diagonals from a square matrix, using the fact that you can use 1-dimensional indexing since matrices are just vectors under the hood and these diagonals correspond to certain arithmetical sequences of indices:

    udiag <- function(A,i,j){
      n <- nrow(A)
      a <- i + n*(j-1) - (n-1)*min(n-i,j-1)
      b <- i + n*(j-1) + (n-1)*min(i-1,n-j)
      A[seq(a,b,n-1)]
    }
    
    ddiag <- function(A,i,j){
      n <- nrow(A)
      a <- i + n*(j-1) - (n+1)*min(i-1,j-1)
      b <- i + n*(j-1) + (n+1)*min(n-i,n-j)
      A[seq(a,b,n+1)]
    }
    

    These two functions extract the upward slanting and downward slanting diagonals respectively. You can use these two functions and write your safe like this:

    safe <- function(x,y){
      i <- x[1]
      j <- x[2]
      sum(y[i,]) == 0 & sum(y[,j]) == 0 & sum(udiag(y,i,j)) == 0 & sum(ddiag(y,i,j)) == 0
    }
    

    On Edit: In view of the intended application, I wrote udiag() and ddiag() to work with square matrices only. Since they may have other uses in potentially nonsquare matrices, they can be easily modified to handle such cases:

    udiag <- function(A,i,j){
      m <- nrow(A)
      n <- ncol(A)
      a <- i + m*(j-1) - (m-1)*min(m-i,j-1)
      b <- i + m*(j-1) + (m-1)*min(i-1,n-j)
      A[seq(a,b,m-1)]
    }
    
    ddiag <- function(A,i,j){
      m <- nrow(A)
      n <- ncol(A)
      a <- i + m*(j-1) - (m+1)*min(i-1,j-1)
      b <- i + m*(j-1) + (m+1)*min(m-i,n-j)
      A[seq(a,b,m+1)]
    }
    

    For example:

    > A <- matrix(1:12,nrow = 3)
    > A
         [,1] [,2] [,3] [,4]
    [1,]    1    4    7   10
    [2,]    2    5    8   11
    [3,]    3    6    9   12
    > udiag(A,2,3)
    [1]  6  8 10
    > ddiag(A,2,3)
    [1]  4  8 12