ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Bash N-Queens Solver (Backtracking)

Bash

Goal -- WPM

Ready
Exercise Algorithm Area
1#!/bin/bash
2
3# N-Queens problem solver using backtracking
4# Goal: Place N queens on an NxN chessboard such that no two queens threaten each other.
5
6# Global variable to store the board configuration
7# board[row]=col means a queen is at (row, col)
8board=()
9
10# Function to check if placing a queen at (row, col) is safe
11# Args: row, col
12# Returns: 0 if safe, 1 if not safe
13is_safe() {
14local row=$1
15local col=$2
16
17# Check this row on left side (not needed as we place one queen per row)
18# Check upper diagonal on left side
19for (( i=0, j=col; i<row && j>=0; i++, j-- )); do
20if [[ ${board[i]} -eq $j ]]; then
21return 1 # Conflict
22fi
23done
24
25# Check lower diagonal on left side
26for (( i=0, j=col; i<row && j<N; i++, j++ )); do
27if [[ ${board[i]} -eq $j ]]; then
28return 1 # Conflict
29fi
30done
31
32# Check this column on upper side
33for (( i=0; i<row; i++ )); do
34if [[ ${board[i]} -eq $col ]]; then
35return 1 # Conflict
36fi
37done
38
39return 0 # Safe
40}
41
42# Recursive function to solve N-Queens problem
43# Args: current row to place a queen
44# Returns: 0 if a solution is found, 1 otherwise
45solve_nqueens_util() {
46local row=$1
47
48# Base case: If all queens are placed, print the solution
49if [[ $row -eq N ]]; then
50print_solution
51return 0 # Found a solution
52fi
53
54# Consider this row and try placing this queen in all columns one by one
55for (( col=0; col<N; col++ )); do
56# Check if the queen can be placed on board[row][col]
57if is_safe $row $col;
58then
59# Place this queen in board[row][col]
60board[$row]=$col
61
62# Recur to place rest of the queens
63if [[ $(solve_nqueens_util $((row + 1))) -eq 0 ]]; then
64return 0 # Solution found
65fi
66
67# If placing queen in board[row][col] doesn't lead to a solution,
68# then remove queen from board[row][col] (backtrack)
69# No explicit removal needed as board[$row] will be overwritten in next iteration or call
70fi
71done
72
73# If the queen cannot be placed in any column in this row, return false
74return 1
75}
76
77# Function to print the board configuration
78print_solution() {
79echo "Solution found:"
80for (( i=0; i<N; i++ )); do
81local line=""
82for (( j=0; j<N; j++ )); do
83if [[ ${board[i]} -eq $j ]]; then
84line+="Q "
85else
86line+=". "
87fi
88done
89echo "$line"
90done
91echo ""
92}
93
94# Main function to solve N-Queens
95# Args: N (size of the board)
96main_nqueens() {
97N=$1
98
99# Initialize board
100for (( i=0; i<N; i++ )); do
101board[$i]=-1 # -1 indicates no queen placed yet
102done
103
104# Call the recursive helper function to solve the problem
105if [[ $(solve_nqueens_util 0) -eq 0 ]]; then
106echo "Successfully found all solutions for N=$N."
107else
108echo "No solution exists for N=$N."
109fi
110}
111
112# Example usage:
113# main_nqueens 4
Algorithm description viewbox

Bash N-Queens Solver (Backtracking)

Algorithm description:

This Bash script implements a backtracking algorithm to solve the N-Queens problem. The goal is to place N chess queens on an NxN chessboard such that no two queens threaten each other. The script uses a recursive function `solve_nqueens_util` to explore possible placements, and `is_safe` to check for conflicts. This is a classic example of a combinatorial problem solved efficiently with recursion and backtracking, applicable in areas like constraint satisfaction and puzzle solving.

Algorithm explanation:

The N-Queens problem is solved using a recursive backtracking approach. The `solve_nqueens_util` function attempts to place a queen in each row, starting from row 0. For each row, it iterates through all columns. Before placing a queen, `is_safe` is called to check if the proposed position `(row, col)` is under attack by any previously placed queens. `is_safe` checks for conflicts in the same column and both diagonals. If a position is safe, the queen is placed (by storing the column index in the `board` array for that row), and the function recursively calls itself for the next row. If the recursive call returns successfully (meaning a solution was found down that path), the current function also returns success. If placing a queen in a column doesn't lead to a solution, the algorithm backtracks by implicitly undoing the placement (the `board` entry will be overwritten in the next iteration or recursive call) and trying the next column. The base case for the recursion is when all N queens have been successfully placed (i.e., `row == N`). The time complexity is roughly O(N!), as in the worst case, it explores many branches of the search tree. The space complexity is O(N) for the recursion stack and the board representation. The invariant is that at any point, the queens placed in rows `0` to `row-1` are in a valid, non-attacking configuration.

Pseudocode:

function solve_nqueens(N):
  initialize empty board of size NxN
  call solve_nqueens_util(0)

function solve_nqueens_util(row):
  if row == N:
    print solution
    return success
  
  for col from 0 to N-1:
    if is_safe(row, col):
      place queen at (row, col)
      if solve_nqueens_util(row + 1) is success:
        return success
      remove queen from (row, col) (backtrack)
  
  return failure

function is_safe(row, col):
  check column for conflicts
  check upper-left diagonal for conflicts
  check lower-left diagonal for conflicts
  return true if safe, false otherwise

function print_solution():
  display the board with queens