queens.py 2.2 KB

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