1

Problem Statement: Given a N*N board with the Knight placed on the first block of an empty board. Moving according to the rules of chess knight must visit each square exactly once. Print the order of each cell in which they are visited on the chess board. If there are more than one solutions possible, print all of them.

Input :
N = 8
Output:
0  59  38  33  30  17   8  63
37  34  31  60   9  62  29  16
58   1  36  39  32  27  18   7
35  48  41  26  61  10  15  28
42  57   2  49  40  23   6  19
47  50  45  54  25  20  11  14
56  43  52   3  22  13  24   5
51  46  55  44  53   4  21  12

I tried a recursive solution using backtracking but do not quite understand what could be the problem with this piece of code. Could someone please help. Thanks a lot!

for n=2,3,4 it produces an empty list which is expected. and for n=5, it produces the following unexpected output:

[[[0, '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.']], [[0, '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.']]] ..continues

for n=8, the program keeps running and does not seem to produce an output for a long time

def knight(n):
  xy_movements = [(2,1),(2,-1),(-2,1),(-2,-1),(1,2),(-1,2),(1,-2),(-1,-2)]
  board = [["."]*n for _ in range(n)]
  board[0][0]=0
  current_x=0
  current_y=0
  result=[]

  def backtrack(num):    
    nonlocal n,current_x,current_y
    if num==(n*n)-1:
      result.append(board)
      return
    else:
      for move in xy_movements:
        if current_x+move[0]<0 or current_x+move[0]>=n or\
           current_y+move[1]<0 or current_y+move[1]>=n or\
           board[current_x+move[0]][current_y+move[1]] !=".":
          continue
        else:
          current_x+=move[0]
          current_y+=move[1]
          board[current_x][current_y] = num+1
          backtrack(num+1)
        
        board[current_x][current_y] = "."
        current_x -= move[0]
        current_y -= move[1]

  backtrack(0)
  return result
13
  • 1
    You mention that there is a problem with this code, but you don't explain what the problem is. Please edit your question to explain why this code doesn't do what you expect it to. E.g. does it throw an exception? Does it appear to run forever and generate no output? Does it generate incorrect output? Commented May 18, 2024 at 16:10
  • @LukeWoodward Done. Have edited my code and included the output that i am getting. Commented May 18, 2024 at 16:18
  • Doesn't work. Try copy'n'pasting the code into a file and running it. Also see minimal reproducible example. BTW: Take a look at PEP 8, it mandates four spaces indent. Adhering to these standards makes it easier for others to quickly and correctly read and understand your code. Commented May 18, 2024 at 16:23
  • For testing, I would start with chess boards with side lengths 1 (trivially solvable), 2, 3 (both unsolvable) and the smalles larger one that is solvable. This will make it easier to understand and debug. Commented May 18, 2024 at 16:25
  • 1
    Fine, but now the example input/output is not complete (nor could it be in practical terms): it just lists one solution. Commented May 18, 2024 at 17:05

1 Answer 1

2

The problem is that result.append(board) will append the only board you have, while your backtracking algorithm will continue to update that board, and at the very end of the algorithm will have taken back all moves it did. So then board is empty, except for the first 0 that was placed and never removed. This means that in result you now reference an almost empty board, even though solutions were found.

The solution is simple: take a copy of the board, and append that board to the result list:

            result.append([row[:] for row in board])

This will solve the issue you mention when calling knight(5). For boards larger than 6, you will just have a problem that is too great: there are 19,591,828,170,979,904 solutions for an 8x8 board, so don't hope to get that in a few seconds. Your PC will probably not have enough memory to collect that many boards, let be you can wait for it.

Sign up to request clarification or add additional context in comments.

7 Comments

Sorry i had a query. Doesn't result append all those boards which have a final number as n*n-1? Could you clarify a bit more please
Yes, I confirm. It is the same as saying that result appends all completed boards. What clarification is needed? If you don't copy the board, you are appending a reference to the same board over and over again, so that all elements in result are actually the same board, which is the board you are constantly updating during the algorithm.
Would really appreciate some more clarification on why result.append(board) doesn't work as intended. Thank you for the answer above!
Imagine you have a real chessboard, and you place a new knight physically on the board at each square (and each knight has a unique number). At some point you find that you have filled the whole board. You place the chessboard will all pieces on it in a box, thinking you have "saved" the board. But then you continue removing knights from that chessboard and try different setups, and then clear all pieces from it. What is the chessboard in the box? It is empty. The fact that you placed the board in the box didn't do anything significant to the board. Same with result.append(board)
"it should have displayed all the other number": But you didn't display it at that moment. You delayed the displaying until the every end, when you had already removed the pieces again from that board.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.