1#! /usr/bin/env python
2
3"""N queens problem.
4
5The (well-known) problem is due to Niklaus Wirth.
6
7This solution is inspired by Dijkstra (Structured Programming).  It is
8a classic recursive backtracking approach.
9
10"""
11
12N = 8                                   # Default; command line overrides
13
14class Queens:
15
16    def __init__(self, n=N):
17        self.n = n
18        self.reset()
19
20    def reset(self):
21        n = self.n
22        self.y = [None] * n             # Where is the queen in column x
23        self.row = [0] * n              # Is row[y] safe?
24        self.up = [0] * (2*n-1)         # Is upward diagonal[x-y] safe?
25        self.down = [0] * (2*n-1)       # Is downward diagonal[x+y] safe?
26        self.nfound = 0                 # Instrumentation
27
28    def solve(self, x=0):               # Recursive solver
29        for y in range(self.n):
30            if self.safe(x, y):
31                self.place(x, y)
32                if x+1 == self.n:
33                    self.display()
34                else:
35                    self.solve(x+1)
36                self.remove(x, y)
37
38    def safe(self, x, y):
39        return not self.row[y] and not self.up[x-y] and not self.down[x+y]
40
41    def place(self, x, y):
42        self.y[x] = y
43        self.row[y] = 1
44        self.up[x-y] = 1
45        self.down[x+y] = 1
46
47    def remove(self, x, y):
48        self.y[x] = None
49        self.row[y] = 0
50        self.up[x-y] = 0
51        self.down[x+y] = 0
52
53    silent = 0                          # If true, count solutions only
54
55    def display(self):
56        self.nfound = self.nfound + 1
57        if self.silent:
58            return
59        print '+-' + '--'*self.n + '+'
60        for y in range(self.n-1, -1, -1):
61            print '|',
62            for x in range(self.n):
63                if self.y[x] == y:
64                    print "Q",
65                else:
66                    print ".",
67            print '|'
68        print '+-' + '--'*self.n + '+'
69
70def main():
71    import sys
72    silent = 0
73    n = N
74    if sys.argv[1:2] == ['-n']:
75        silent = 1
76        del sys.argv[1]
77    if sys.argv[1:]:
78        n = int(sys.argv[1])
79    q = Queens(n)
80    q.silent = silent
81    q.solve()
82    print "Found", q.nfound, "solutions."
83
84if __name__ == "__main__":
85    main()
86