17db96d56Sopenharmony_ci#!/usr/bin/env python3 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci""" 47db96d56Sopenharmony_ciN queens problem. 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciThe (well-known) problem is due to Niklaus Wirth. 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciThis solution is inspired by Dijkstra (Structured Programming). It is 97db96d56Sopenharmony_cia classic recursive backtracking approach. 107db96d56Sopenharmony_ci""" 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ciN = 8 # Default; command line overrides 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ciclass Queens: 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci def __init__(self, n=N): 177db96d56Sopenharmony_ci self.n = n 187db96d56Sopenharmony_ci self.reset() 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci def reset(self): 217db96d56Sopenharmony_ci n = self.n 227db96d56Sopenharmony_ci self.y = [None] * n # Where is the queen in column x 237db96d56Sopenharmony_ci self.row = [0] * n # Is row[y] safe? 247db96d56Sopenharmony_ci self.up = [0] * (2*n-1) # Is upward diagonal[x-y] safe? 257db96d56Sopenharmony_ci self.down = [0] * (2*n-1) # Is downward diagonal[x+y] safe? 267db96d56Sopenharmony_ci self.nfound = 0 # Instrumentation 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci def solve(self, x=0): # Recursive solver 297db96d56Sopenharmony_ci for y in range(self.n): 307db96d56Sopenharmony_ci if self.safe(x, y): 317db96d56Sopenharmony_ci self.place(x, y) 327db96d56Sopenharmony_ci if x+1 == self.n: 337db96d56Sopenharmony_ci self.display() 347db96d56Sopenharmony_ci else: 357db96d56Sopenharmony_ci self.solve(x+1) 367db96d56Sopenharmony_ci self.remove(x, y) 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci def safe(self, x, y): 397db96d56Sopenharmony_ci return not self.row[y] and not self.up[x-y] and not self.down[x+y] 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci def place(self, x, y): 427db96d56Sopenharmony_ci self.y[x] = y 437db96d56Sopenharmony_ci self.row[y] = 1 447db96d56Sopenharmony_ci self.up[x-y] = 1 457db96d56Sopenharmony_ci self.down[x+y] = 1 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci def remove(self, x, y): 487db96d56Sopenharmony_ci self.y[x] = None 497db96d56Sopenharmony_ci self.row[y] = 0 507db96d56Sopenharmony_ci self.up[x-y] = 0 517db96d56Sopenharmony_ci self.down[x+y] = 0 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci silent = 0 # If true, count solutions only 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci def display(self): 567db96d56Sopenharmony_ci self.nfound = self.nfound + 1 577db96d56Sopenharmony_ci if self.silent: 587db96d56Sopenharmony_ci return 597db96d56Sopenharmony_ci print('+-' + '--'*self.n + '+') 607db96d56Sopenharmony_ci for y in range(self.n-1, -1, -1): 617db96d56Sopenharmony_ci print('|', end=' ') 627db96d56Sopenharmony_ci for x in range(self.n): 637db96d56Sopenharmony_ci if self.y[x] == y: 647db96d56Sopenharmony_ci print("Q", end=' ') 657db96d56Sopenharmony_ci else: 667db96d56Sopenharmony_ci print(".", end=' ') 677db96d56Sopenharmony_ci print('|') 687db96d56Sopenharmony_ci print('+-' + '--'*self.n + '+') 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_cidef main(): 717db96d56Sopenharmony_ci import sys 727db96d56Sopenharmony_ci silent = 0 737db96d56Sopenharmony_ci n = N 747db96d56Sopenharmony_ci if sys.argv[1:2] == ['-n']: 757db96d56Sopenharmony_ci silent = 1 767db96d56Sopenharmony_ci del sys.argv[1] 777db96d56Sopenharmony_ci if sys.argv[1:]: 787db96d56Sopenharmony_ci n = int(sys.argv[1]) 797db96d56Sopenharmony_ci q = Queens(n) 807db96d56Sopenharmony_ci q.silent = silent 817db96d56Sopenharmony_ci q.solve() 827db96d56Sopenharmony_ci print("Found", q.nfound, "solutions.") 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ciif __name__ == "__main__": 857db96d56Sopenharmony_ci main() 86