| 
									
										
										
										
											2010-03-11 22:53:45 +00:00
										 |  |  | #! /usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | """N queens problem.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The (well-known) problem is due to Niklaus Wirth. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This solution is inspired by Dijkstra (Structured Programming).  It is | 
					
						
							|  |  |  | a classic recursive backtracking approach. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | N = 8                                   # Default; command line overrides | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Queens: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, n=N): | 
					
						
							|  |  |  |         self.n = n | 
					
						
							|  |  |  |         self.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def reset(self): | 
					
						
							|  |  |  |         n = self.n | 
					
						
							| 
									
										
										
										
											2009-10-11 14:27:51 +00:00
										 |  |  |         self.y = [None] * n             # Where is the queen in column x | 
					
						
							|  |  |  |         self.row = [0] * n              # Is row[y] safe? | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  |         self.up = [0] * (2*n-1)         # Is upward diagonal[x-y] safe? | 
					
						
							|  |  |  |         self.down = [0] * (2*n-1)       # Is downward diagonal[x+y] safe? | 
					
						
							|  |  |  |         self.nfound = 0                 # Instrumentation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def solve(self, x=0):               # Recursive solver | 
					
						
							|  |  |  |         for y in range(self.n): | 
					
						
							|  |  |  |             if self.safe(x, y): | 
					
						
							|  |  |  |                 self.place(x, y) | 
					
						
							|  |  |  |                 if x+1 == self.n: | 
					
						
							|  |  |  |                     self.display() | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     self.solve(x+1) | 
					
						
							|  |  |  |                 self.remove(x, y) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def safe(self, x, y): | 
					
						
							|  |  |  |         return not self.row[y] and not self.up[x-y] and not self.down[x+y] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def place(self, x, y): | 
					
						
							|  |  |  |         self.y[x] = y | 
					
						
							|  |  |  |         self.row[y] = 1 | 
					
						
							|  |  |  |         self.up[x-y] = 1 | 
					
						
							|  |  |  |         self.down[x+y] = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def remove(self, x, y): | 
					
						
							|  |  |  |         self.y[x] = None | 
					
						
							|  |  |  |         self.row[y] = 0 | 
					
						
							|  |  |  |         self.up[x-y] = 0 | 
					
						
							|  |  |  |         self.down[x+y] = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-11 14:27:51 +00:00
										 |  |  |     silent = 0                          # If true, count solutions only | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def display(self): | 
					
						
							|  |  |  |         self.nfound = self.nfound + 1 | 
					
						
							|  |  |  |         if self.silent: | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |         print('+-' + '--'*self.n + '+') | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  |         for y in range(self.n-1, -1, -1): | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |             print('|', end=' ') | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  |             for x in range(self.n): | 
					
						
							|  |  |  |                 if self.y[x] == y: | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |                     print("Q", end=' ') | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |                     print(".", end=' ') | 
					
						
							|  |  |  |             print('|') | 
					
						
							|  |  |  |         print('+-' + '--'*self.n + '+') | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     import sys | 
					
						
							|  |  |  |     silent = 0 | 
					
						
							|  |  |  |     n = N | 
					
						
							|  |  |  |     if sys.argv[1:2] == ['-n']: | 
					
						
							|  |  |  |         silent = 1 | 
					
						
							|  |  |  |         del sys.argv[1] | 
					
						
							|  |  |  |     if sys.argv[1:]: | 
					
						
							|  |  |  |         n = int(sys.argv[1]) | 
					
						
							|  |  |  |     q = Queens(n) | 
					
						
							|  |  |  |     q.silent = silent | 
					
						
							|  |  |  |     q.solve() | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |     print("Found", q.nfound, "solutions.") | 
					
						
							| 
									
										
										
										
											2000-11-16 21:25:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main() |