From 148388763f7e9c1fd88e1ef0b033e24aa67ed31d Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 29 Jun 2020 15:51:14 -0600 Subject: [PATCH 01/19] add new file for another solution to the n queens problem --- backtracking/n_queens_math.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 backtracking/n_queens_math.py diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py new file mode 100644 index 000000000000..e69de29bb2d1 From 105d9eee68c3b73707b5b6471180ccfad27470f9 Mon Sep 17 00:00:00 2001 From: David Banda Date: Sat, 4 Jul 2020 18:19:41 -0600 Subject: [PATCH 02/19] Add the code for the algorithm, add comments and add at the top a general explanation --- backtracking/n_queens_math.py | 140 ++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index e69de29bb2d1..abcf746ba753 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -0,0 +1,140 @@ +""" + Problem: + + The n queens 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: + + To solve this problem we will use simple math. First we know the queen can move in all + the possible ways, we can simplify it in this: vertical, horizontal, diagonal left and + diagonal right. + + We can visualize it like this: left diagonal = \ and right diagonal = / + + On a chessboard vertical movement could be the rows and horizontal movement could be the columns. + In programming we can use an array, and in this array each index could be the rows and + each value in the array could be the column. For example: + + . Q . . We have this chessboard with one queen in each column and each queen + . . . Q can't attack to each other. + Q . . . The array for this example would look like this: [1, 3, 0, 2] + . . Q . + + So if we use an array and we verify that each value in the array is different to each other + we know that at least the queens can't attack each other in horizontal and vertical. + + At this point we have tha halfway completed and we will treat the chessboard as a Cartesian plane. + Hereinafter we are going to remember basic math, so in the school we learned this formula: + + Slope of a line: + + y2 - y1 + m = ---------- + x2 - x1 + + This formula allow us to get the slope. For the angles 45º (right diagonal) and + 135º (left diagonal) this formula gives us m = 1, and m = -1 respectively + (here a lit more information: + https://www.enotes.com/homework-help/write-equation-line-that-hits-origin-45-degree-1474860). + + Then we have this another formula: + + Slope intercept: + + y = mx + b + + b is where the line crosses the Y axis (to get more information see here: https://www.mathsisfun.com/y_intercept.html), + if we change the formula to solve for b we would have: + + y - mx = b + + And like we already have the m values for the angles 45º and 135º, this formula + would look like this: + + 45º: y - (1)x = b + 45º: y - x = b + + 135º: y - (-1)x = b + 135º: y + x = b + + y = row + x = column + + Applying this two formulas we can check if a queen in some position + is being attacked for another one or vice versa. + + +""" + + +def n_queens_solution(n): + """ boards is the variable (array) in where we are gonna store all the boards + in where the queens not attack to each other """ + boards = [] + + """ dfs is the function in where we found all the boards. + + - First paramether: we pass the possible current board to add to our variable boards + - Second paramether: Is a variable to store diagonal right collisions for the queens in the + First paramether (possible_board). + - Third paramether: Same as Second paramether but for diagonal left collisions. + """ + dfs([], [], [], boards, n) + + """ Print all the boards """ + for board in boards: + for column in board: + print(column) + print('') + + print("The total no. of solutions are :", len(boards)) + + +def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boards, n): + + """ Get next row in the current board (possible_board) to fill it with a queen """ + row = len(possible_board) + + """ If row is equal to the size of the board it means there are a queen in each row + in the current board (possible_board) """ + if row == n: + """ We convert the variable possible_board that looks like this: [1, 3, 0, 2] + to this: ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] """ + possible_board = ['. ' * i + 'Q ' + '. ' * (n - 1 - i) for i in possible_board] + + """ Then we add it to the 'boards' global variable """ + boards.append(possible_board) + return + + """ We iterate each column in the row to find all possible results in each row """ + for col in range(n): + + """ We apply that we learned previously. First we check that in the current board + (possible_board) there are not other same value because if there is it means that there + are a collision in vertical. Then we apply the two formulas we learned before: + + 45º: y - x = b or 45: row - col = b + 135º: y + x = b or row + col = b. + + And we verify if the results of this two formulas not exist in their + variables respectively. (diagonal_right_collisions, diagonal_left_collisions) + + If some of this is True we continue to the other value in the for loop because it + means there are a collision """ + if col in possible_board or row - col in diagonal_right_collisions or row + col in diagonal_left_collisions: + continue + + """ If it is False we call dfs function again and we update the inputs """ + dfs(possible_board + [col], + diagonal_right_collisions + [row - col], + diagonal_left_collisions + [row + col], + boards, n) + + +n_queens_solution(4) + + From 52223884c782033283687ae7351f1d6957057946 Mon Sep 17 00:00:00 2001 From: David Aaron Banda Gutierrez <44423937+DavidBanda@users.noreply.github.com> Date: Sat, 4 Jul 2020 22:30:27 -0600 Subject: [PATCH 03/19] Update backtracking/n_queens_math.py Co-authored-by: Christian Clauss --- backtracking/n_queens_math.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index abcf746ba753..26ce60198f71 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -15,7 +15,8 @@ We can visualize it like this: left diagonal = \ and right diagonal = / - On a chessboard vertical movement could be the rows and horizontal movement could be the columns. + On a chessboard vertical movement could be the rows and horizontal movement could be + the columns. In programming we can use an array, and in this array each index could be the rows and each value in the array could be the column. For example: @@ -137,4 +138,3 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa n_queens_solution(4) - From e65b5a70d950a2783df522ef79792fe687aed061 Mon Sep 17 00:00:00 2001 From: David Aaron Banda Gutierrez <44423937+DavidBanda@users.noreply.github.com> Date: Sat, 4 Jul 2020 22:30:37 -0600 Subject: [PATCH 04/19] Update backtracking/n_queens_math.py Co-authored-by: Christian Clauss --- backtracking/n_queens_math.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 26ce60198f71..76ad6caeda36 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -77,7 +77,7 @@ def n_queens_solution(n): in where the queens not attack to each other """ boards = [] - """ dfs is the function in where we found all the boards. + """ dfs is the function in where we found all the boards. - First paramether: we pass the possible current board to add to our variable boards - Second paramether: Is a variable to store diagonal right collisions for the queens in the @@ -137,4 +137,3 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa n_queens_solution(4) - From 6692361d62fe1e8785b97fb2e4a010403ee1ed92 Mon Sep 17 00:00:00 2001 From: David Aaron Banda Gutierrez <44423937+DavidBanda@users.noreply.github.com> Date: Sat, 4 Jul 2020 22:30:45 -0600 Subject: [PATCH 05/19] Update backtracking/n_queens_math.py Co-authored-by: Christian Clauss --- backtracking/n_queens_math.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 76ad6caeda36..7d870c5d6d9f 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -78,7 +78,6 @@ def n_queens_solution(n): boards = [] """ dfs is the function in where we found all the boards. - - First paramether: we pass the possible current board to add to our variable boards - Second paramether: Is a variable to store diagonal right collisions for the queens in the First paramether (possible_board). From 9e6d572761ee35baa07f52512e82e945a558cf32 Mon Sep 17 00:00:00 2001 From: David Aaron Banda Gutierrez <44423937+DavidBanda@users.noreply.github.com> Date: Sat, 4 Jul 2020 22:31:09 -0600 Subject: [PATCH 06/19] Update backtracking/n_queens_math.py Co-authored-by: Christian Clauss --- backtracking/n_queens_math.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 7d870c5d6d9f..24a815e56752 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -1,4 +1,4 @@ -""" +r""" Problem: The n queens problem is of placing N queens on a N * N From 2af2536d77fc95b0595407c203a65dea353e5682 Mon Sep 17 00:00:00 2001 From: David Banda Date: Sat, 4 Jul 2020 22:35:37 -0600 Subject: [PATCH 07/19] No newline at the end of the file --- backtracking/n_queens_math.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 24a815e56752..3dba69760f4a 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -135,4 +135,4 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa boards, n) -n_queens_solution(4) +n_queens_solution(4) \ No newline at end of file From 42a5cfbcb1d6e52bfc0f8a0b107198a3a02cc9b6 Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 6 Jul 2020 12:54:44 -0600 Subject: [PATCH 08/19] Type hints --- backtracking/n_queens_math.py | 96 ++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 3dba69760f4a..cd8468e5f2fb 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -9,27 +9,37 @@ Solution: - To solve this problem we will use simple math. First we know the queen can move in all - the possible ways, we can simplify it in this: vertical, horizontal, diagonal left and + To solve this problem we will use simple math. First we know + the queen can move in all the possible ways, we can + simplify it in this: vertical, horizontal, diagonal left and diagonal right. - We can visualize it like this: left diagonal = \ and right diagonal = / + We can visualize it like this: - On a chessboard vertical movement could be the rows and horizontal movement could be - the columns. - In programming we can use an array, and in this array each index could be the rows and - each value in the array could be the column. For example: + left diagonal = \ + right diagonal = / + + On a chessboard vertical movement could be the rows + and horizontal movement could be the columns. + + In programming we can use an array, and in this + array each index could be the rows and each value in + the array could be the column. For example: . Q . . We have this chessboard with one queen in each column and each queen . . . Q can't attack to each other. Q . . . The array for this example would look like this: [1, 3, 0, 2] . . Q . - So if we use an array and we verify that each value in the array is different to each other - we know that at least the queens can't attack each other in horizontal and vertical. + So if we use an array and we verify that each + value in the array is different to each other we + know that at least the queens can't attack each other + in horizontal and vertical. - At this point we have tha halfway completed and we will treat the chessboard as a Cartesian plane. - Hereinafter we are going to remember basic math, so in the school we learned this formula: + At this point we have tha halfway completed and we will treat + the chessboard as a Cartesian plane. + Hereinafter we are going to remember basic math, + so in the school we learned this formula: Slope of a line: @@ -37,8 +47,9 @@ m = ---------- x2 - x1 - This formula allow us to get the slope. For the angles 45º (right diagonal) and - 135º (left diagonal) this formula gives us m = 1, and m = -1 respectively + This formula allow us to get the slope. For the angles 45º ( + right diagonal) and 135º (left diagonal) this formula gives us + m = 1, and m = -1 respectively (here a lit more information: https://www.enotes.com/homework-help/write-equation-line-that-hits-origin-45-degree-1474860). @@ -48,13 +59,14 @@ y = mx + b - b is where the line crosses the Y axis (to get more information see here: https://www.mathsisfun.com/y_intercept.html), + b is where the line crosses the Y axis (to get + more information see here: https://www.mathsisfun.com/y_intercept.html), if we change the formula to solve for b we would have: y - mx = b - And like we already have the m values for the angles 45º and 135º, this formula - would look like this: + And like we already have the m values for the angles + 45º and 135º, this formula would look like this: 45º: y - (1)x = b 45º: y - x = b @@ -65,23 +77,27 @@ y = row x = column - Applying this two formulas we can check if a queen in some position - is being attacked for another one or vice versa. + Applying this two formulas we can check + if a queen in some position is being attacked + for another one or vice versa. """ def n_queens_solution(n): - """ boards is the variable (array) in where we are gonna store all the boards - in where the queens not attack to each other """ + """ boards is the variable (array) in where we are + gonna store all the boards in where the queens + not attack to each other """ boards = [] """ dfs is the function in where we found all the boards. - - First paramether: we pass the possible current board to add to our variable boards - - Second paramether: Is a variable to store diagonal right collisions for the queens in the - First paramether (possible_board). - - Third paramether: Same as Second paramether but for diagonal left collisions. + - First paramether: we pass the possible current board + to add to our variable boards + - Second paramether: Is a variable to store diagonal right + collisions for the queens in the First paramether (possible_board). + - Third paramether: Same as Second paramether but + for diagonal left collisions. """ dfs([], [], [], boards, n) @@ -96,13 +112,16 @@ def n_queens_solution(n): def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boards, n): - """ Get next row in the current board (possible_board) to fill it with a queen """ + """ Get next row in the current board (possible_board) to + fill it with a queen """ row = len(possible_board) - """ If row is equal to the size of the board it means there are a queen in each row + """ If row is equal to the size of the board it + means there are a queen in each row in the current board (possible_board) """ if row == n: - """ We convert the variable possible_board that looks like this: [1, 3, 0, 2] + """ We convert the variable possible_board that + looks like this: [1, 3, 0, 2] to this: ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] """ possible_board = ['. ' * i + 'Q ' + '. ' * (n - 1 - i) for i in possible_board] @@ -110,25 +129,30 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa boards.append(possible_board) return - """ We iterate each column in the row to find all possible results in each row """ + """ We iterate each column in the row to find all + possible results in each row """ for col in range(n): - """ We apply that we learned previously. First we check that in the current board - (possible_board) there are not other same value because if there is it means that there - are a collision in vertical. Then we apply the two formulas we learned before: + """ We apply that we learned previously. First we check + that in the current board (possible_board) there are + not other same value because if there is it means that there + are a collision in vertical. Then we apply the two formulas + we learned before: 45º: y - x = b or 45: row - col = b 135º: y + x = b or row + col = b. - And we verify if the results of this two formulas not exist in their - variables respectively. (diagonal_right_collisions, diagonal_left_collisions) + And we verify if the results of this two formulas not + exist in their variables respectively. + (diagonal_right_collisions, diagonal_left_collisions) - If some of this is True we continue to the other value in the for loop because it - means there are a collision """ + If some of this is True we continue to the other value in + the for loop because it means there are a collision """ if col in possible_board or row - col in diagonal_right_collisions or row + col in diagonal_left_collisions: continue - """ If it is False we call dfs function again and we update the inputs """ + """ If it is False we call dfs function again and + we update the inputs """ dfs(possible_board + [col], diagonal_right_collisions + [row - col], diagonal_left_collisions + [row + col], From c82159868764cafa875309b925b09c28e2dad653 Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 6 Jul 2020 13:04:58 -0600 Subject: [PATCH 09/19] whitespaces fixed --- backtracking/n_queens_math.py | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index cd8468e5f2fb..eba2a196e9df 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -92,11 +92,11 @@ def n_queens_solution(n): boards = [] """ dfs is the function in where we found all the boards. - - First paramether: we pass the possible current board + - First paramether: we pass the possible current board to add to our variable boards - - Second paramether: Is a variable to store diagonal right - collisions for the queens in the First paramether (possible_board). - - Third paramether: Same as Second paramether but + - Second paramether: Is a variable to store diagonal right + collisions for the queens in the First paramether (possible_board). + - Third paramether: Same as Second paramether but for diagonal left collisions. """ dfs([], [], [], boards, n) @@ -117,11 +117,11 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa row = len(possible_board) """ If row is equal to the size of the board it - means there are a queen in each row + means there are a queen in each row in the current board (possible_board) """ if row == n: - """ We convert the variable possible_board that - looks like this: [1, 3, 0, 2] + """ We convert the variable possible_board that + looks like this: [1, 3, 0, 2] to this: ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] """ possible_board = ['. ' * i + 'Q ' + '. ' * (n - 1 - i) for i in possible_board] @@ -129,29 +129,30 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa boards.append(possible_board) return - """ We iterate each column in the row to find all + """ We iterate each column in the row to find all possible results in each row """ for col in range(n): - """ We apply that we learned previously. First we check - that in the current board (possible_board) there are - not other same value because if there is it means that there - are a collision in vertical. Then we apply the two formulas - we learned before: - + """ We apply that we learned previously. First we check + that in the current board (possible_board) there are + not other same value because if there is it means that there + are a collision in vertical. Then we apply the two formulas + we learned before: + 45º: y - x = b or 45: row - col = b 135º: y + x = b or row + col = b. - And we verify if the results of this two formulas not - exist in their variables respectively. + And we verify if the results of this two formulas not + exist in their variables respectively. (diagonal_right_collisions, diagonal_left_collisions) - If some of this is True we continue to the other value in + If some of this is True we continue to the other value in the for loop because it means there are a collision """ - if col in possible_board or row - col in diagonal_right_collisions or row + col in diagonal_left_collisions: + if col in possible_board or row - col in diagonal_right_collisions \ + or row + col in diagonal_left_collisions: continue - """ If it is False we call dfs function again and + """ If it is False we call dfs function again and we update the inputs """ dfs(possible_board + [col], diagonal_right_collisions + [row - col], @@ -159,4 +160,4 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa boards, n) -n_queens_solution(4) \ No newline at end of file +n_queens_solution(4) From b62b637829ac0423c5d34ef474e07c4341aeebf8 Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 6 Jul 2020 13:13:20 -0600 Subject: [PATCH 10/19] Fixed whitespaces --- backtracking/n_queens_math.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index eba2a196e9df..f3c818731903 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -138,14 +138,14 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa not other same value because if there is it means that there are a collision in vertical. Then we apply the two formulas we learned before: - + 45º: y - x = b or 45: row - col = b 135º: y + x = b or row + col = b. - + And we verify if the results of this two formulas not exist in their variables respectively. (diagonal_right_collisions, diagonal_left_collisions) - + If some of this is True we continue to the other value in the for loop because it means there are a collision """ if col in possible_board or row - col in diagonal_right_collisions \ From 2bd7aee2afb52bfce50ccd5c500b1272375f6d96 Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 6 Jul 2020 13:44:37 -0600 Subject: [PATCH 11/19] Add type hints --- backtracking/n_queens_math.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index f3c818731903..5fa17d870e43 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -81,14 +81,10 @@ if a queen in some position is being attacked for another one or vice versa. - """ def n_queens_solution(n): - """ boards is the variable (array) in where we are - gonna store all the boards in where the queens - not attack to each other """ boards = [] """ dfs is the function in where we found all the boards. @@ -111,6 +107,14 @@ def n_queens_solution(n): def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boards, n): + """ + :type possible_board: list + :type diagonal_right_collisions: list + :type diagonal_left_collisions: list + :type boards: list + :type n: int + :return: None + """ """ Get next row in the current board (possible_board) to fill it with a queen """ From 0f96b60e42170e9bcc95fc8540914ac202213472 Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 6 Jul 2020 13:52:16 -0600 Subject: [PATCH 12/19] CodeSpell fixed --- backtracking/n_queens_math.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 5fa17d870e43..47f16fa0136c 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -36,7 +36,7 @@ know that at least the queens can't attack each other in horizontal and vertical. - At this point we have tha halfway completed and we will treat + At this point we have that halfway completed and we will treat the chessboard as a Cartesian plane. Hereinafter we are going to remember basic math, so in the school we learned this formula: From af938a05003acafe183c62da9a3ca769856af85c Mon Sep 17 00:00:00 2001 From: David Banda Date: Mon, 6 Jul 2020 14:11:24 -0600 Subject: [PATCH 13/19] update --- backtracking/n_queens_math.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 47f16fa0136c..dce464ea48e1 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -113,7 +113,6 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa :type diagonal_left_collisions: list :type boards: list :type n: int - :return: None """ """ Get next row in the current board (possible_board) to From 6989f838f5420d7f86c441e1e24fd6d534bb1e18 Mon Sep 17 00:00:00 2001 From: David Banda Date: Tue, 7 Jul 2020 13:21:57 -0600 Subject: [PATCH 14/19] All changes made except changing the board variable to local --- backtracking/n_queens_math.py | 79 +++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index dce464ea48e1..42fd13bc16bd 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -82,37 +82,24 @@ for another one or vice versa. """ +from typing import List -def n_queens_solution(n): - boards = [] - - """ dfs is the function in where we found all the boards. - - First paramether: we pass the possible current board - to add to our variable boards - - Second paramether: Is a variable to store diagonal right - collisions for the queens in the First paramether (possible_board). - - Third paramether: Same as Second paramether but - for diagonal left collisions. - """ - dfs([], [], [], boards, n) - - """ Print all the boards """ - for board in boards: - for column in board: - print(column) - print('') - - print("The total no. of solutions are :", len(boards)) - - -def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boards, n): +def depth_first_search( + possible_board: List[int], + diagonal_right_collisions: List[int], + diagonal_left_collisions: List[int], + boards: List[List[str]], + n: int +) -> None: """ - :type possible_board: list - :type diagonal_right_collisions: list - :type diagonal_left_collisions: list - :type boards: list - :type n: int + >>> depth_first_search( + ... possible_board = [], + ... diagonal_right_collisions = [], + ... diagonal_left_collisions = [], + ... boards= [], + ... n = 4) + [['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '], ['. . Q . ', 'Q . . . ', '. . . Q ', '. Q . . ']] """ """ Get next row in the current board (possible_board) to @@ -127,8 +114,6 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa looks like this: [1, 3, 0, 2] to this: ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] """ possible_board = ['. ' * i + 'Q ' + '. ' * (n - 1 - i) for i in possible_board] - - """ Then we add it to the 'boards' global variable """ boards.append(possible_board) return @@ -151,16 +136,36 @@ def dfs(possible_board, diagonal_right_collisions, diagonal_left_collisions, boa If some of this is True we continue to the other value in the for loop because it means there are a collision """ - if col in possible_board or row - col in diagonal_right_collisions \ - or row + col in diagonal_left_collisions: + if (col in possible_board + or row - col in diagonal_right_collisions + or row + col in diagonal_left_collisions): + continue """ If it is False we call dfs function again and we update the inputs """ - dfs(possible_board + [col], - diagonal_right_collisions + [row - col], - diagonal_left_collisions + [row + col], - boards, n) + depth_first_search(possible_board + [col], + diagonal_right_collisions + [row - col], + diagonal_left_collisions + [row + col], + boards, n) + + +def n_queens_solution(n: int) -> None: + + boards = [] + depth_first_search([], [], [], boards, n) + + """ Print all the boards """ + for board in boards: + for column in board: + print(column) + print('') + + print("The total no. of solutions are :", len(boards)) + +if __name__ == '__main__': + import doctest + doctest.testmod() + n_queens_solution(4) -n_queens_solution(4) From 7c63b77462d040c8c50e348be255bc6f50dcf529 Mon Sep 17 00:00:00 2001 From: David Banda Date: Tue, 7 Jul 2020 14:05:17 -0600 Subject: [PATCH 15/19] Add doctest --- backtracking/n_queens_math.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 42fd13bc16bd..16e53592a314 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -93,12 +93,9 @@ def depth_first_search( n: int ) -> None: """ - >>> depth_first_search( - ... possible_board = [], - ... diagonal_right_collisions = [], - ... diagonal_left_collisions = [], - ... boards= [], - ... n = 4) + >>> boards = [] + >>> depth_first_search([], [], [], boards, 4) + >>> boards [['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '], ['. . Q . ', 'Q . . . ', '. . . Q ', '. Q . . ']] """ @@ -166,6 +163,6 @@ def n_queens_solution(n: int) -> None: if __name__ == '__main__': import doctest - doctest.testmod() + doctest.testmod(extraglobs={'boards': []}) n_queens_solution(4) From 68b573dbfbe0d32899f752054b2b78306a78003d Mon Sep 17 00:00:00 2001 From: David Banda Date: Tue, 7 Jul 2020 14:14:26 -0600 Subject: [PATCH 16/19] Update --- backtracking/n_queens_math.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 16e53592a314..4951b41df843 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -95,8 +95,10 @@ def depth_first_search( """ >>> boards = [] >>> depth_first_search([], [], [], boards, 4) - >>> boards - [['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '], ['. . Q . ', 'Q . . . ', '. . . Q ', '. Q . . ']] + >>> for board in boards: + ... print(board) + ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] + ['. . Q . ', 'Q . . . ', '. . . Q ', '. Q . . '] """ """ Get next row in the current board (possible_board) to @@ -136,7 +138,6 @@ def depth_first_search( if (col in possible_board or row - col in diagonal_right_collisions or row + col in diagonal_left_collisions): - continue """ If it is False we call dfs function again and @@ -148,12 +149,12 @@ def depth_first_search( def n_queens_solution(n: int) -> None: - boards = [] depth_first_search([], [], [], boards, n) """ Print all the boards """ for board in boards: + print(board) for column in board: print(column) print('') @@ -163,6 +164,6 @@ def n_queens_solution(n: int) -> None: if __name__ == '__main__': import doctest + doctest.testmod(extraglobs={'boards': []}) n_queens_solution(4) - From de33d23c4418dcd1ef234629e1eb108926f135d9 Mon Sep 17 00:00:00 2001 From: David Banda Date: Tue, 7 Jul 2020 14:16:09 -0600 Subject: [PATCH 17/19] Update --- backtracking/n_queens_math.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 4951b41df843..d825c292ebfe 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -154,7 +154,6 @@ def n_queens_solution(n: int) -> None: """ Print all the boards """ for board in boards: - print(board) for column in board: print(column) print('') @@ -164,6 +163,5 @@ def n_queens_solution(n: int) -> None: if __name__ == '__main__': import doctest - doctest.testmod(extraglobs={'boards': []}) n_queens_solution(4) From 26eb205a91e4c61eb8f2fd325da2ebafe815b0ac Mon Sep 17 00:00:00 2001 From: David Banda Date: Tue, 7 Jul 2020 14:41:48 -0600 Subject: [PATCH 18/19] Update --- backtracking/n_queens_math.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index d825c292ebfe..e681d7de5642 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -163,5 +163,5 @@ def n_queens_solution(n: int) -> None: if __name__ == '__main__': import doctest - doctest.testmod(extraglobs={'boards': []}) + doctest.testmod() n_queens_solution(4) From 6fbceb5e9209b1b4197e665679cf16905e1b49b1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 10 Jul 2020 10:19:52 +0200 Subject: [PATCH 19/19] Update n_queens_math.py --- backtracking/n_queens_math.py | 182 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 92 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index e681d7de5642..fb2b74bd7c4a 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -1,45 +1,39 @@ r""" - Problem: +Problem: - The n queens 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. +The n queens 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: +Solution: - To solve this problem we will use simple math. First we know - the queen can move in all the possible ways, we can - simplify it in this: vertical, horizontal, diagonal left and +To solve this problem we will use simple math. First we know the queen can move in all +the possible ways, we can simplify it in this: vertical, horizontal, diagonal left and diagonal right. - We can visualize it like this: +We can visualize it like this: - left diagonal = \ - right diagonal = / +left diagonal = \ +right diagonal = / - On a chessboard vertical movement could be the rows - and horizontal movement could be the columns. +On a chessboard vertical movement could be the rows and horizontal movement could be +the columns. - In programming we can use an array, and in this - array each index could be the rows and each value in - the array could be the column. For example: +In programming we can use an array, and in this array each index could be the rows and +each value in the array could be the column. For example: . Q . . We have this chessboard with one queen in each column and each queen . . . Q can't attack to each other. Q . . . The array for this example would look like this: [1, 3, 0, 2] . . Q . - So if we use an array and we verify that each - value in the array is different to each other we - know that at least the queens can't attack each other - in horizontal and vertical. +So if we use an array and we verify that each value in the array is different to each +other we know that at least the queens can't attack each other in horizontal and +vertical. - At this point we have that halfway completed and we will treat - the chessboard as a Cartesian plane. - Hereinafter we are going to remember basic math, - so in the school we learned this formula: +At this point we have that halfway completed and we will treat the chessboard as a +Cartesian plane. Hereinafter we are going to remember basic math, so in the school we +learned this formula: Slope of a line: @@ -47,50 +41,49 @@ m = ---------- x2 - x1 - This formula allow us to get the slope. For the angles 45º ( - right diagonal) and 135º (left diagonal) this formula gives us - m = 1, and m = -1 respectively - (here a lit more information: - https://www.enotes.com/homework-help/write-equation-line-that-hits-origin-45-degree-1474860). +This formula allow us to get the slope. For the angles 45º (right diagonal) and 135º +(left diagonal) this formula gives us m = 1, and m = -1 respectively. - Then we have this another formula: +See:: +https://www.enotes.com/homework-help/write-equation-line-that-hits-origin-45-degree-1474860 - Slope intercept: +Then we have this another formula: - y = mx + b +Slope intercept: - b is where the line crosses the Y axis (to get - more information see here: https://www.mathsisfun.com/y_intercept.html), - if we change the formula to solve for b we would have: +y = mx + b - y - mx = b +b is where the line crosses the Y axis (to get more information see: +https://www.mathsisfun.com/y_intercept.html), if we change the formula to solve for b +we would have: - And like we already have the m values for the angles - 45º and 135º, this formula would look like this: +y - mx = b - 45º: y - (1)x = b - 45º: y - x = b +And like we already have the m values for the angles 45º and 135º, this formula would +look like this: - 135º: y - (-1)x = b - 135º: y + x = b +45º: y - (1)x = b +45º: y - x = b - y = row - x = column +135º: y - (-1)x = b +135º: y + x = b - Applying this two formulas we can check - if a queen in some position is being attacked - for another one or vice versa. +y = row +x = column + +Applying this two formulas we can check if a queen in some position is being attacked +for another one or vice versa. """ from typing import List def depth_first_search( - possible_board: List[int], - diagonal_right_collisions: List[int], - diagonal_left_collisions: List[int], - boards: List[List[str]], - n: int + possible_board: List[int], + diagonal_right_collisions: List[int], + diagonal_left_collisions: List[int], + boards: List[List[str]], + n: int, ) -> None: """ >>> boards = [] @@ -101,51 +94,55 @@ def depth_first_search( ['. . Q . ', 'Q . . . ', '. . . Q ', '. Q . . '] """ - """ Get next row in the current board (possible_board) to - fill it with a queen """ + """ Get next row in the current board (possible_board) to fill it with a queen """ row = len(possible_board) - """ If row is equal to the size of the board it - means there are a queen in each row - in the current board (possible_board) """ + """ + If row is equal to the size of the board it means there are a queen in each row in + the current board (possible_board) + """ if row == n: - """ We convert the variable possible_board that - looks like this: [1, 3, 0, 2] - to this: ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] """ - possible_board = ['. ' * i + 'Q ' + '. ' * (n - 1 - i) for i in possible_board] + """ + We convert the variable possible_board that looks like this: [1, 3, 0, 2] to + this: ['. Q . . ', '. . . Q ', 'Q . . . ', '. . Q . '] + """ + possible_board = [". " * i + "Q " + ". " * (n - 1 - i) for i in possible_board] boards.append(possible_board) return - """ We iterate each column in the row to find all - possible results in each row """ + """ We iterate each column in the row to find all possible results in each row """ for col in range(n): - """ We apply that we learned previously. First we check - that in the current board (possible_board) there are - not other same value because if there is it means that there - are a collision in vertical. Then we apply the two formulas - we learned before: - - 45º: y - x = b or 45: row - col = b - 135º: y + x = b or row + col = b. - - And we verify if the results of this two formulas not - exist in their variables respectively. - (diagonal_right_collisions, diagonal_left_collisions) - - If some of this is True we continue to the other value in - the for loop because it means there are a collision """ - if (col in possible_board - or row - col in diagonal_right_collisions - or row + col in diagonal_left_collisions): + """ + We apply that we learned previously. First we check that in the current board + (possible_board) there are not other same value because if there is it means + that there are a collision in vertical. Then we apply the two formulas we + learned before: + + 45º: y - x = b or 45: row - col = b + 135º: y + x = b or row + col = b. + + And we verify if the results of this two formulas not exist in their variables + respectively. (diagonal_right_collisions, diagonal_left_collisions) + + If any or these are True it means there is a collision so we continue to the + next value in the for loop. + """ + if ( + col in possible_board + or row - col in diagonal_right_collisions + or row + col in diagonal_left_collisions + ): continue - """ If it is False we call dfs function again and - we update the inputs """ - depth_first_search(possible_board + [col], - diagonal_right_collisions + [row - col], - diagonal_left_collisions + [row + col], - boards, n) + """ If it is False we call dfs function again and we update the inputs """ + depth_first_search( + possible_board + [col], + diagonal_right_collisions + [row - col], + diagonal_left_collisions + [row + col], + boards, + n, + ) def n_queens_solution(n: int) -> None: @@ -156,12 +153,13 @@ def n_queens_solution(n: int) -> None: for board in boards: for column in board: print(column) - print('') + print("") - print("The total no. of solutions are :", len(boards)) + print(len(boards), "solutions were found.") -if __name__ == '__main__': +if __name__ == "__main__": import doctest + doctest.testmod() n_queens_solution(4)