/Demo/scripts/queens.py

http://unladen-swallow.googlecode.com/ · Python · 85 lines · 63 code · 13 blank · 9 comment · 14 complexity · 14ea69976d102fa11af3966ef4865305 MD5 · raw file

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