1
- """ N-Queens solutions . """
1
+ """ Backtracking solution to N-Queens problem . """
2
2
3
3
__author__ = "Caleb Madrigal"
4
4
__date__ = "2015-02-19"
@@ -22,25 +22,23 @@ def right_to_left_diagonals_valid(board):
22
22
[ 56. 57. 58. 59. 60. 61. 62. 63.]]
23
23
24
24
It checks right-to-left columns in 2 steps:
25
- * First, it checks each right-to-left diagonal that begins with each element on the first row
25
+ * Step 1: it checks each right-to-left diagonal that begins with each element on the first row
26
26
(skipping the first index, since that "diagonal" is just element[0]) So the indices
27
27
of each start of each row-based diagonal are: 1, 2, 3, 4, 5, 6, 7. In order to find the
28
28
indices of each subsequent element in each diagonal, it adds (size-1) to the initial
29
29
diagonal. For example: if we are checking the right-to-left diagonal starting with index 2,
30
30
the diagonal should be indices: 2, 9, 16 (each is separated by 7). In order to perform
31
31
this math, the nxn matrix is flattened.
32
- * Second, it does roughly the same thing for the right-to-left diagonals that start on the
32
+ * Step 2: it does roughly the same thing for the right-to-left diagonals that start on the
33
33
far-right column (indices 15, 23, 31, 39, 47, 55, 63). """
34
34
35
35
size = len (board )
36
36
flat = board .reshape ((1 , size * size ))[0 ]
37
- # Check right-to-left diagonals
37
+
38
38
for row_index in range (1 , size ):
39
- #print("row_index:", row_index)
40
39
index = row_index
41
40
diag_sum = 0
42
41
for diag_index in range (row_index + 1 ):
43
- #print("\tdiag_index: {0}, value: {1}".format(index, flat[index]))
44
42
diag_sum += flat [index ]
45
43
index += (size - 1 )
46
44
if diag_sum > 1 :
@@ -49,13 +47,11 @@ def right_to_left_diagonals_valid(board):
49
47
col_diag_index = 0
50
48
diag_lengths = list (range (size - 1 , 0 , - 1 ))
51
49
for last_col_index in range (2 * size - 1 , size * size - 1 , size ):
52
- #print("col_index:", last_col_index)
53
50
index = last_col_index
54
51
diag_sum = 0
55
52
diag_len = diag_lengths [col_diag_index ]
56
53
col_diag_index += 1
57
54
for diag_index in range (diag_len ):
58
- #print("\tdiag_index: {0}, value: {1}".format(index, flat[index]))
59
55
diag_sum += flat [index ]
60
56
index += (size - 1 )
61
57
if diag_sum > 1 :
@@ -80,43 +76,15 @@ def diags_valid(board):
80
76
return right_to_left_diagonals_valid (board ) and left_to_right_diagonals_valid (board )
81
77
82
78
83
- def rows_valid (board ):
84
- """ Returns True if there are no more than 1 "1" in any row; else False. """
85
-
86
- for row in board :
87
- if np .sum (row ) > 1 :
88
- return False
89
- return True
90
-
91
-
92
- def cols_valid (board ):
93
- """ Returns True if there are no more than 1 "1" in any column; else False. """
94
-
95
- for col_index in range (len (board )):
96
- if np .sum (board [:, col_index ]) > 1 :
97
- return False
98
- return True
99
-
100
-
101
- def is_valid (board ):
102
- """ Returns True if there are no more than 1 "1" in any row, column, or diagonal;
103
- Else, it returns False. """
104
-
105
- # We only have to check that the diagonals are valid, since the search
106
- # algorithm doesn't put more than 1 queen on a given row or column
107
- #return rows_valid(board) and cols_valid(board) and diags_valid(board)
108
- return diags_valid (board )
109
-
110
-
111
79
def print_board_indented (board , row ):
112
80
print ('\t ' * row + str (board ).replace ('\n ' , '\n ' + ('\t ' * row )))
113
81
114
82
115
83
def search (board , row = 0 , cols_taken = ()):
116
- """ In-place search for solution to n-queens. """
84
+ """ In-place search for solution to n-queens. Backtracking algorithm. """
117
85
118
86
# Return if we are at the maximum depth and the solution is valid
119
- if row == len (board ) and is_valid (board ):
87
+ if row == len (board ) and diags_valid (board ):
120
88
return True
121
89
122
90
# Otherwise, try each column and recursively work down the rows
@@ -127,7 +95,7 @@ def search(board, row=0, cols_taken=()):
127
95
board [row ][col ] = 1
128
96
print_board_indented (board , row )
129
97
130
- if is_valid (board ):
98
+ if diags_valid (board ):
131
99
if search (board , row + 1 , cols_taken + (col ,)):
132
100
return True
133
101
else :
@@ -149,3 +117,4 @@ def n_queens(size):
149
117
if __name__ == '__main__' :
150
118
board_size = 8
151
119
n_queens (board_size )
120
+
0 commit comments