#945 Backtracking Algorithms (#953)

* Adding nqueens.py for backtracking

* Adding sum_of_subsets.py for backtracking

* Update nqueens.py

* Rename nqueens.py to n_queens.py

* Deleting /other/n_queens.py
This commit is contained in:
Hetal Kuvadia 2019-07-05 14:18:36 +05:30 committed by Anup Kumar Panwar
parent afb98e6c23
commit 831558d38d
3 changed files with 129 additions and 77 deletions

84
backtracking/n_queens.py Normal file
View File

@ -0,0 +1,84 @@
'''
The nqueens problem is of placing N queens on a N * N
chess board such that no queen can attack any other queens placed
on that chess board.
This means that one queen cannot have any other queen on its horizontal, vertical and
diagonal lines.
'''
solution = []
def isSafe(board, row, column):
'''
This function returns a boolean value True if it is safe to place a queen there considering
the current state of the board.
Parameters :
board(2D matrix) : board
row ,column : coordinates of the cell on a board
Returns :
Boolean Value
'''
for i in range(len(board)):
if board[row][i] == 1:
return False
for i in range(len(board)):
if board[i][column] == 1:
return False
for i,j in zip(range(row,-1,-1),range(column,-1,-1)):
if board[i][j] == 1:
return False
for i,j in zip(range(row,-1,-1),range(column,len(board))):
if board[i][j] == 1:
return False
return True
def solve(board, row):
'''
It creates a state space tree and calls the safe function untill it receives a
False Boolean and terminates that brach and backtracks to the next
poosible solution branch.
'''
if row >= len(board):
'''
If the row number exceeds N we have board with a successful combination
and that combination is appended to the solution list and the board is printed.
'''
solution.append(board)
printboard(board)
print()
return
for i in range(len(board)):
'''
For every row it iterates through each column to check if it is feesible to place a
queen there.
If all the combinations for that particaular branch are successfull the board is
reinitialized for the next possible combination.
'''
if isSafe(board,row,i):
board[row][i] = 1
solve(board,row+1)
board[row][i] = 0
return False
def printboard(board):
'''
Prints the boards that have a successfull combination.
'''
for i in range(len(board)):
for j in range(len(board)):
if board[i][j] == 1:
print("Q", end = " ")
else :
print(".", end = " ")
print()
#n=int(input("The no. of queens"))
n = 8
board = [[0 for i in range(n)]for j in range(n)]
solve(board, 0)
print("The total no. of solutions are :", len(solution))

View File

@ -0,0 +1,45 @@
'''
The sum-of-subsetsproblem states that a set of non-negative integers, and a value M,
determine all possible subsets of the given set whose summation sum equal to given M.
Summation of the chosen numbers must be equal to given number M and one number can
be used only once.
'''
def generate_sum_of_subsets_soln(nums, max_sum):
result = []
path = []
num_index = 0
remaining_nums_sum = sum(nums)
create_state_space_tree(nums, max_sum, num_index, path,result, remaining_nums_sum)
return result
def create_state_space_tree(nums,max_sum,num_index,path,result, remaining_nums_sum):
'''
Creates a state space tree to iterate through each branch using DFS.
It terminates the branching of a node when any of the two conditions
given below satisfy.
This algorithm follows depth-fist-search and backtracks when the node is not branchable.
'''
if sum(path) > max_sum or (remaining_nums_sum + sum(path)) < max_sum:
return
if sum(path) == max_sum:
result.append(path)
return
for num_index in range(num_index,len(nums)):
create_state_space_tree(nums, max_sum, num_index + 1, path + [nums[num_index]], result, remaining_nums_sum - nums[num_index])
'''
remove the comment to take an input from the user
print("Enter the elements")
nums = list(map(int, input().split()))
print("Enter max_sum sum")
max_sum = int(input())
'''
nums = [3, 34, 4, 12, 5, 2]
max_sum = 9
result = generate_sum_of_subsets_soln(nums,max_sum)
print(*result)

View File

@ -1,77 +0,0 @@
#! /usr/bin/python3
import sys
def nqueens(board_width):
board = [0]
current_row = 0
while True:
conflict = False
for review_index in range(0, current_row):
left = board[review_index] - (current_row - review_index)
right = board[review_index] + (current_row - review_index);
if (board[current_row] == board[review_index] or (left >= 0 and left == board[current_row]) or (right < board_width and right == board[current_row])):
conflict = True;
break
if (current_row == 0 and conflict == False):
board.append(0)
current_row = 1
continue
if (conflict == True):
board[current_row] += 1
if (current_row == 0 and board[current_row] == board_width):
print("No solution exists for specificed board size.")
return None
while True:
if (board[current_row] == board_width):
board[current_row] = 0
if (current_row == 0):
print("No solution exists for specificed board size.")
return None
board.pop()
current_row -= 1
board[current_row] += 1
if board[current_row] != board_width:
break
else:
current_row += 1
if (current_row == board_width):
break
board.append(0)
return board
def print_board(board):
if (board == None):
return
board_width = len(board)
for row in range(board_width):
line_print = []
for column in range(board_width):
if column == board[row]:
line_print.append("Q")
else:
line_print.append(".")
print(line_print)
if __name__ == '__main__':
default_width = 8
for arg in sys.argv:
if (arg.isdecimal() and int(arg) > 3):
default_width = int(arg)
break
if (default_width == 8):
print("Running algorithm with board size of 8. Specify an alternative Chess board size for N-Queens as a command line argument.")
board = nqueens(default_width)
print(board)
print_board(board)