Tuesday, August 23, 2016

Eight queens on a chess board

Question: The challenge is to place 8 queens (ministers) on a chess board so that no 2 queens are in the same row or same column or same diagonal. The solution in C# is given below:

The approach is to place a queen at a position only if there are no other queens in the row or column or the diagonals that the new queen is being placed on. In a normal approach, this would be mean checking the row, column and both the diagonals (which would be O(6n) operations - n for rows, n for columns, 2n each for the diagonals). In my approach, I have used 4 arrays - rowArray, colArray, leadingArray and trailingArray, tha last 2 of which are for the diagonals). If any rows of column 0 are filled, the element 0 of the column array will be filled. Similar is the case with row array. While the row and column arrays have a length of 8, the diagonal arrays have a length of 15. This is because we want to cover all the cells being mapped to an array - eg. cell (7, 0) maps to element 0 in the leading array and cells (6, 0) and (7, 1) map to element 1 in the leading array and this goes on. Similar is the case with trailing array.

The approach is as follows - try o put a queen in each of the columns in a row. Once a queen can be successfully be placed, pass the state and try to place a queen in the next row. If a queen cannot be placed in a (row, col) combination, try to move to the next col for the same row and keep continuing. Finally if a queen can be placed in the last row, save the state of the board in the finalist and return. At this point, we remove the queen and try to put it in another location and try again.

class EightQueensOnBoardAllCombinations
    {
        private bool[] rowArray = new bool[8];
        private bool[] colArray = new bool[8];
        private bool[] leadingArray = new bool[15];
        private bool[] trailngArray = new bool[15];
        private List<List<KeyValuePair<int, int>>> finalList = new List<List<KeyValuePair<int, int>>>();
       
        /// <summary>
        /// Method that can be called from an external method
        /// </summary>
        public static void Test()
        {
            var instance = new EightQueensOnBoardAllCombinations();
            instance.Arrange();
        }

        /// <summary>
        /// Entry method to start placing the queens
        /// </summary>
        public void Arrange()
        {
            List<KeyValuePair<int, int>> rtnList;
            for (var row = 0; row <= 7; row++)
            {
                PlaceQueens(0, row, new List<KeyValuePair<int, int>>());
            }
            foreach (var list in finalList)
            {
                PrintBoard(list);
                Console.WriteLine();
            }
            Console.WriteLine("Total number of combinations = {0}", finalList.Count);
        }

        /// <summary>
        /// Prints the board of queens
        /// </summary>
        /// <param name="rtnList"></param>
        private void PrintBoard(List<KeyValuePair<int, int>> rtnList)
        {
            foreach (var kvp in rtnList)
            {
                Console.WriteLine(kvp.Key + ", " + kvp.Value);
                RemoveQueen(kvp.Key, kvp.Value);
            }
        }

        /// <summary>
        /// Given a row where a queen was already placed and the number of queens already placed,
        /// returns a list of KVPs on where queens could be placed, and null if there is no possible combination
        /// </summary>
        /// <param name="num"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        private void PlaceQueens(int num, int row, List<KeyValuePair<int, int>> input)
        {
           
            for (var col = 0; col <= 7; col ++)
            {
                if (PlaceQueen(row, col) == true)
                {
                    var newInput = new List<KeyValuePair<int, int>>();
                    newInput.AddRange(input);
                    newInput.Add(new KeyValuePair<int, int>(row, col));
                    if (num < 7)
                    {
                        PlaceQueens(num + 1, (row + 1) % 8, newInput);
                    }
                    else
                    {
                        finalList.Add(newInput);
                    }
                    RemoveQueen(row, col);
                }
            }
            return;
        }

        /// <summary>
        /// Given a row and column on the chess board, returns true if a queeen could be placed there, else returns false
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        private bool PlaceQueen(int row, int col)
        {
            if (rowArray[row] == true)
            {
                return false;
            }
            if (colArray[col] == true)
            {
                return false;
            }
            var leadingDiagonal = col + 7 - row;
            if (leadingArray[leadingDiagonal] == true)
            {
                return false;
            }
            var trailingDiagonal = col + row;
            if (trailngArray[trailingDiagonal] == true)
            {
                return false;
            }
            rowArray[row] = true;
            colArray[col] = true;
            leadingArray[leadingDiagonal] = true;
            trailngArray[trailingDiagonal] = true;
            return true;
        }

        /// <summary>
        /// Method to remove a queen at a row and col on the board
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        private void RemoveQueen(int row, int col)
        {
            rowArray[row] = false;
            colArray[col] = false;
            var leadingDiagonal = col + 7 - row;
            leadingArray[leadingDiagonal] = false;
            var trailingDiagonal = col + row;
            trailngArray[trailingDiagonal] = false;
        }
    }





























































































No comments:

Post a Comment

Comments