#!/usr/bin/env python3 | |
""" | |
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 | |
self.y = [None] * n # Where is the queen in column x | |
self.row = [0] * n # Is row[y] safe? | |
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 | |
silent = 0 # If true, count solutions only | |
def display(self): | |
self.nfound = self.nfound + 1 | |
if self.silent: | |
return | |
print('+-' + '--'*self.n + '+') | |
for y in range(self.n-1, -1, -1): | |
print('|', end=' ') | |
for x in range(self.n): | |
if self.y[x] == y: | |
print("Q", end=' ') | |
else: | |
print(".", end=' ') | |
print('|') | |
print('+-' + '--'*self.n + '+') | |
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() | |
print("Found", q.nfound, "solutions.") | |
if __name__ == "__main__": | |
main() | |