nathanwailes

Backtracking

Mar 26th, 2024 (edited)
730
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.90 KB | None | 0 0
  1. """
  2. Backtracking is a systematic way of trying out different sequences of decisions until we find one that "works." It's often used for solving problems related to constraints, such as puzzles (like Sudoku), combinatorial problems, and pathfinding in mazes.
  3.  
  4. A classic example of a problem solved using backtracking is the N-Queens puzzle. The challenge is to place N queens on an N×N chessboard so that no two queens threaten each other. This means no two queens can be in the same row, column, or diagonal.
  5.  
  6. Here's a simple Python solution using backtracking. This solution focuses on placing one queen in each row, starting from the first row and moving downwards. If a valid position is found, the algorithm proceeds to the next row; if not, it backtracks.
  7.  
  8. The code below defines a chessboard as a 2D list, where '.' represents an empty square and 'Q' represents a queen. The solve_n_queens function tries to place queens on the board in a way that no two queens attack each other. The is_safe function checks if a queen can be placed at the specified row and column considering the current state of the board. The solve function attempts to place a queen in every row of a particular column before moving on to the next column, and it backtracks if no safe position is found.
  9.  
  10. For an n of 4, this will generate all the possible solutions where the queens don't attack each other.
  11.  
  12. Pseudocode:
  13.  
  14. backtracking:
  15.    # define empty results obj
  16.    # initialize cache-like object to track global state
  17.    # start recursive function at one end of the object looking for solutions
  18.    # return results
  19.  
  20.    # recursive function:
  21.        # check edge cases / add solution to results
  22.        # if the current position is OK to proceed down based on what you've seen so far, update global state, recurse from here, then update global state to undo your change.
  23.  
  24.  
  25. Note that the code for checking the diagonals is trickier/fancier than it may first look:
  26. 1) it depends on the behavior of the zip() function in which it will stop creating new pairs once one of the input ranges runs out of indices, thereby preventing an out-of-bounds error.
  27. 2) The fact that it is iterating "backwards" starting from the row/col and then moving left towards the left edge of the board, rather than iterating from the left edge of the board to the right, is actually by design; it's necessary to do it that way to ensure you're looking along the correct diagonals. I once tried to do the iteration from the left and it turned out that I was actually just iterating from the top-left / bottom-left corners every time.
  28. """
  29.  
  30.  
  31. def backtracking(n):
  32.     board = [['.' for _ in range(n)] for _ in range(n)]
  33.     results = []
  34.    
  35.     def is_safe(row, col):
  36.         # Check this row on left side
  37.         for c in range(col):
  38.             if board[row][c] == 'Q':
  39.                 return False
  40.        
  41.         # Check upper diagonal on left side
  42.         for r, c in zip(range(row, -1, -1), range(col, -1, -1)):
  43.             if board[r][c] == 'Q':
  44.                 return False
  45.        
  46.         # Check lower diagonal on left side
  47.         for r, c in zip(range(row, n), range(col, -1, -1)):
  48.             if board[r][c] == 'Q':
  49.                 return False
  50.        
  51.         return True
  52.    
  53.     def solve(col):
  54.         # If all queens are placed
  55.         if col >= n:
  56.             results.append([''.join(row) for row in board])
  57.             return
  58.        
  59.         # Consider this column and try placing this queen in all rows one by one
  60.         for row in range(n):
  61.             if is_safe(row, col):
  62.                 board[row][col] = 'Q'
  63.                 solve(col + 1)  # Recurse to place rest of the queens
  64.                 board[row][col] = '.'  # Remove the queen to check for other possible solutions
  65.                
  66.     solve(0)
  67.     return results
  68.  
  69. # Example usage
  70. n = 4
  71. for solution in backtracking(n):
  72.     for row in solution:
  73.         print(row)
  74.     print()
Advertisement
Add Comment
Please, Sign In to add comment