def _do_loadFromURL(self): print "open url" from tkSimpleDialog import askstring filename = askstring( _("Enter the URL"), _("Enter the URL"), initialvalue="http://sudoku.udl.es/Problems/Easy-4-1.gpe") if not isinstance(filename, basestring): return self.StatusBar.set(_("Opening %s, please wait...") % (filename, )) import urllib2 as urllib from tkMessageBox import showinfo try: f = urllib.urlopen(filename) bkgrid = Sudoku.Grid() bkgrid.copy_values_from(self._grid) grid = Sudoku.Grid() if filename.lower().endswith(".gpe"): ftype = "gpe" else: ftype = "tsdk" grid.load_from_stream(f, ftype) self._grid.copy_values_from(grid) if bkgrid != grid: self._history_callback("t", bkgrid, grid) f.close() except Sudoku.Contradiction: f.close() showinfo(message=_("Invalid sudoku file"), title=_("Invalid sudoku file")) except urllib.HTTPError, detail: showinfo( message=_("The server said:\n%s\nRequesting the %s resource") % (detail, filename), title=_("Remote server error"))
def _do_new(self): bkgrid = Sudoku.Grid() bkgrid.copy_values_from(self._grid) void = Sudoku.Grid() if bkgrid != void: self._history_callback("t", bkgrid, void) self._grid.reset()
def OnNew(self, evt): #self.SudokuGrid.Reset() import wxNewSudokuDialog dlg = wxNewSudokuDialog.NewSudokuDialog(self) dlg.ShowModal() if dlg.OkStatus: bkgrid = Sudoku.Grid(self.SudokuGrid._ModelGrid) bkgrid.copy_values_from(self.SudokuGrid._ModelGrid) type = dlg.type.GetValue() sbr = int(dlg.brows.GetValue()) sbc = int(dlg.bcols.GetValue()) c = sbr r = sbc if type == _("Samurai"): su = Sudoku.SamuraiSudoku(r, c, sbr, sbc) else: su = Sudoku.NormalSudoku(r, c, sbr, sbc) self.SetStatusText(_("Creating Sudoku, please wait....")) self.app.Yield() if su != bkgrid._type: self._addSudoku(su) else: self.SudokuGrid.Reset() emptygrid = Sudoku.Grid(su) if bkgrid != emptygrid: self._history_callback("t", bkgrid, emptygrid) self.SetStatusText("") dlg.Destroy()
def keyPressEvent(self, event): """ Handles key presses. If is a number key, update the value in selected cell """ key = event.key() keyStr = event.text() if self.selectedCell and self.selectedCell.CanEdit(): # If number key pressed if QtCore.Qt.Key_1 <= key <= QtCore.Qt.Key_9: self.selectedCell.UpdateValue(keyStr) self.currBoard[self.selectedCell.i][self.selectedCell.j] = int( keyStr) # self.UpdatePossibleCandidates() if key == QtCore.Qt.Key_Backspace: self.selectedCell.UpdateValue(' ') self.currBoard[self.selectedCell.i][self.selectedCell.j] = 0 # self.candBoard = sd.SolveCandidates(self.currBoard) dups = sd.FindDuplicates(self.currBoard) if not sd.CheckValid(dups): print('Invalid', dups) self.ShowInvalidCells(dups)
def solve_sudoku_extra(puzzle): # for testing, always initialize the pseudorandom number generator to output the same sequence # of values: random.seed(41) puzzle_name = str(puzzle) sol_filename = puzzle_name[:-4] + ".sol" sat = SAT(puzzle) start = time.time() result = sat.WalkSAT() total = time.time() - start if puzzle_name[-4:] == ".sud": print("original sudoku puzzle: ") sud = Sudoku() sud.load(puzzle) print(sud) if result: sat.sol_file(sol_filename) print("solution found in " + str(sat.runs) + " iterations of SAT") print("the code took " + str(total) + " seconds to run.") display_sudoku_solution(sol_filename) else: print("no solution found by SAT in " + str(sat.limit) + " iterations of SAT")
def OnOpen(self, evt): dlg = wx.FileDialog(self, wildcard="".join( (_("GPE files"), " (*.gpe)|*.gpe|", _("TSudoku files"), " (*.tsdk)|*.tsdk|", _("All Files"), "|*")), style=wx.OPEN) if dlg.ShowModal() == wx.ID_OK: filep = dlg.GetDirectory() + "/" + dlg.GetFilename() self.SetStatusText(_("Opening %s, please wait...") % (filep, )) self.app.Yield() try: bkgrid = Sudoku.Grid(self.SudokuGrid._ModelGrid) bkgrid.copy_values_from(self.SudokuGrid._ModelGrid) grid = Sudoku.Grid( ) #TODO we must scan de file and get the Sudoku Type grid.load_from_file(filep) if grid._type != bkgrid._type: self._addSudoku(grid._type) self.SudokuGrid._ModelGrid.copy_values_from(grid) if bkgrid != grid: self._history_callback("t", bkgrid, grid) except Sudoku.Contradiction: wx.MessageBox(_("Invalid sudoku file"), _("Invalid sudoku file"), style=wx.ICON_INFORMATION, parent=self) except Exception, detail: wx.MessageBox( _("Malformed, unconsistent, or unexistent file.\n%s") % (detail, ), _("Invalid sudoku file"), style=wx.ICON_ERROR, parent=self)
def _do_loadFromFile(self): # DONE: Check errors !!! from tkFileDialog import askopenfilename filename = askopenfilename(filetypes=((_("GPE files"), "*.gpe"), (_("TSudoku files"), "*.tsdk"), (_("All Files"), "*"))) if not isinstance(filename, basestring) or filename == "": return # Exit if Cancel or Closed self.StatusBar.set(_("Opening %s, please wait...") % (filename, )) try: bkgrid = Sudoku.Grid() bkgrid.copy_values_from(self._grid) grid = Sudoku.Grid() grid.load_from_file(filename) self._grid.copy_values_from(grid) if bkgrid != grid: self._history_callback("t", bkgrid, grid) except Sudoku.Contradiction: # Dialog guarantees filename exists from tkMessageBox import showinfo showinfo(message=_("Invalid sudoku file")) except Exception, detail: # Any other issue, is a filesystem, parse, etc, etc, etc... error from tkMessageBox import showerror showerror(message=( _("Malformed, unconsistent, or unexistent file.\n%s") % (detail, )))
def __init__(self, screen): """ Initializes the game application """ self._grid = Sudoku() # self._screen = screen padding = 20 width, height = screen.get_size() self._text_grid = [[None for _ in range(9)] for _ in range(9)] # Create a Textbox for each cell of the grid for row in range(9): for col in range(9): self._text_grid[row][col] = \ Textbox((width - 2 * padding) * col / 9 + padding, (height - 2 * padding) * row / 9 + padding, (width - 2 * padding) * 1 / 9, (height - 2 * padding) * 1 / 9) # Reads the grid model and displays each cell on the screen for row in range(9): for col in range(9): # 0 is seen as an empty space, and the clues if self._grid.get_cell(row, col) != 0: self._text_grid[row][col].set_text(self._grid.get_cell(row, col)) self._text_grid[row][col].set_editable(False) self._update_tile()
def randomFill(puzzle): locs = Sudoku.checkFilled(puzzle)[1] while not Sudoku.checkCorrect(puzzle)[0]: for i in locs: puzzle[i[0]][i[1]] = random.randint(1, len(puzzle)) return puzzle
def runAstar(): initial_state = Problem.CREATE_INITIAL_STATE() print("Initial State:") print(Problem.DESCRIBE_STATE(initial_state)) global COUNT, BACKLINKS COUNT = 0 BACKLINKS = {} Astar(initial_state) print(str(COUNT) + " states examined.")
def test_check_results(self): puzzle = [[5, 3, 0, 0, 7, 0, 0, 0, 0], [6, 0, 0, 1, 9, 5, 0, 0, 0], [0, 9, 8, 0, 0, 0, 0, 6, 0], [8, 0, 0, 0, 6, 0, 0, 0, 3], [4, 0, 0, 8, 0, 3, 0, 0, 1], [7, 0, 0, 0, 2, 0, 0, 0, 6], [0, 6, 0, 0, 0, 0, 2, 8, 0], [0, 0, 0, 4, 1, 9, 0, 0, 5], [0, 0, 0, 0, 8, 0, 0, 7, 9]] game = Sudoku(puzzle) self.asserter.assertTrue(game.check_results([1, 2, 3])) self.asserter.assertFalse(game.check_results([15, 2, 3]))
def run_app(origBoard): """ Main application function """ print('Board is valid:', sd.BoardIsValid(origBoard)) candBoard = sd.SolveCandidates(origBoard) app = QtWidgets.QApplication(sys.argv) mainWin = SudokuMainWindow(origBoard, candBoard) mainWin.show() return app.exec_()
def backtrace(S): global BACKLINKS path = [] while not S == -1: path.append(S) S = BACKLINKS[Problem.HASHCODE(S)] path.reverse() print("Solution path: ") for s in path: print(Problem.DESCRIBE_STATE(s)) return path
def test_check_for_win(self): puzzle = [[5, 3, 0, 0, 7, 0, 0, 0, 0], [6, 0, 0, 1, 9, 5, 0, 0, 0], [0, 9, 8, 0, 0, 0, 0, 6, 0], [8, 0, 0, 0, 6, 0, 0, 0, 3], [4, 0, 0, 8, 0, 3, 0, 0, 1], [7, 0, 0, 0, 2, 0, 0, 0, 6], [0, 6, 0, 0, 0, 0, 2, 8, 0], [0, 0, 0, 4, 1, 9, 0, 0, 5], [0, 0, 0, 0, 8, 0, 0, 7, 9]] game = Sudoku(puzzle) self.asserter.assertFalse(game.check_for_win()) for i in range(9): for j in range(9): game.puzzle[i][j] = 1 self.asserter.assertTrue(game.check_for_win())
def Solver(puzzle, r, c, search="bfs", printSolution=False): if search == "bfs": call = BFS(Sudoku(puzzle, len(puzzle), r, c)) elif search == "dfs": call = DFS(Sudoku(puzzle, len(puzzle), r, c)) else: call = "Invalid search" if printSolution: if call == None: print("No Solution") return call else: return call
def solve_and_print(file=None, from_string=None, sep='_', n=1): if file: with open(file) as f: X = Sudoku.fromString(f.read(), empty=sep) elif from_string: X = Sudoku.fromString(from_string, empty=sep) X_solved, moves = Sudoku.solve(X) mask = np.zeros([9, 9]) for i in range(min(n, len(moves))): move = moves[i] mask[move[1], move[2]] = 1 X[move[1], move[2]] = move[0] Sudoku.print_sudoku(X, mask)
def remove_test(): grid = Sudoku.Grid(val) grid.remove_elements_in_neighbors() assert (grid.grid[0][0] == "1") for i in range(1, 9): assert (grid.grid[0][i] == "23456789") assert (grid.grid[i][0] == "23456789") assert (grid.grid[1][1] == "23456789") assert (grid.grid[2][1] == "23456789") assert (grid.grid[1][2] == "23456789") assert (grid.grid[2][2] == "23456789") for i in range(1, 9): for j in range(3, 9): assert (grid.grid[i][j] == Sudoku.ALL_NUMS) for i in range(3, 9): assert (grid.grid[i][1] == Sudoku.ALL_NUMS) assert (grid.grid[i][2] == Sudoku.ALL_NUMS) print("remove_elements_in_neighbors test passed")
def neighbors_test(): grid = Sudoku.Grid(val) grid.find_neighbors_of_elem(2, 1) neighbor_list = grid.neighbor_dict[(2, 1)] for i in range(9): if i == 1: continue assert ((2, i) in neighbor_list) for i in range(9): if i == 2: continue assert ((i, 1) in neighbor_list) assert ((0, 0) in neighbor_list) assert ((1, 0) in neighbor_list) assert ((0, 2) in neighbor_list) assert ((1, 2) in neighbor_list) assert ((2, 1) not in neighbor_list) print("find_neighbors_of_elem test passed")
def main(file, show): digits = Sudoku.main(file, show) grid, grid_info = Digits.read_grid(digits) grid = predict(grid, grid_info) show_grid(grid) return grid
def setGrid(self, grid): """ Sets the working grid """ self.startup_grid = Sudoku.Grid(grid) self.stack = [ deepcopy(self.startup_grid), ] self.solution = None
def solve_(self, solve, subs): #Class method used to handle all solve requests. if solve: sudoku = [] for number in Sudoku.boxes: #Uses the box list from Sudoku module to n = self.request.get( str(number + 1) ) #create an accurate conversion from html table to the solver function. if n not in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '']: subs['error'] = "Invalid sudoku" #Checks sudoku return if n: sudoku.append(int(n)) else: sudoku.append('') try: result = Sudoku.solver(sudoku) except ValueError: #This is a more complex check to see if a puzzle was subs[ 'error'] = "Invalid sudoku" #not solvable even though it was return #not immediately apparent. if result == "Invalid sudoku": subs['error'] = "Invalid sudoku" return for number in range( 0, 81 ): #And this reconverts the sudoku back to it's original format subs[str(number + 1)] = result[Sudoku.boxes[ number]] #from the python list and assigns appropriate values to mapping dict.
def __init__(self, handle): super(PeterActivity, self).__init__(handle) # Build the activity toolbar. toolbox = activity.ActivityToolbox(self) activity_toolbar = toolbox.get_activity_toolbar() activity_toolbar.keep.props.visible = False activity_toolbar.share.props.visible = False toolbox.show() self.set_toolbox(toolbox) # Create the game instance. self.game = Sudoku.Sudoku() # Build the Pygame canvas. self._pygamecanvas = \ sugargame.canvas.PygameCanvas(self) # Note that set_canvas implicitly calls # read_file when resuming from the Journal. self.set_canvas(self._pygamecanvas) self.game.canvas = self._pygamecanvas # Start the game running. self._pygamecanvas.run_pygame(self.game.run)
def isSolved(self): for x in Sudoku.getAllPos(self): if type(self.avail[x]) == int: continue else: return False return True
def HighlightHiddenSingles(self): """ Highlight where there are hidden single candidates """ self.ClearHighlights() hiddenSingles = sd.HiddenSingles(self.currBoard, self.candBoard) for hiddenSingle in hiddenSingles: i, j, n = hiddenSingle self.cells[i][j].HiliteCandidates(set([n]))
def OnOpenURL(self, evt): dlg = wx.TextEntryDialog( self, _("Enter the URL"), _("Enter the URL"), defaultValue="http://sudoku.udl.es/Problems/Easy-4-1.gpe") if dlg.ShowModal() == wx.ID_OK: self.SetStatusText( _("Opening %s, please wait...") % (dlg.GetValue(), )) self.app.Yield() import urllib2 as urllib try: f = urllib.urlopen(dlg.GetValue()) bkgrid = Sudoku.Grid(self.SudokuGrid._ModelGrid) bkgrid.copy_values_from(self.SudokuGrid._ModelGrid) grid = Sudoku.Grid( ) #TODO we must scan de file and get the Sudoku Type if dlg.GetValue().lower().endswith(".gpe"): ftype = "gpe" else: ftype = "tsdk" grid.load_from_stream(f, ftype) if grid._type != bkgrid._type: self._addSudoku(grid._type) self.SudokuGrid._ModelGrid.copy_values_from(grid) if bkgrid != grid: self._history_callback("t", bkgrid, grid) f.close() except Sudoku.Contradiction: f.close() wx.MessageBox(_("Invalid sudoku file"), _("Invalid sudoku file"), style=wx.ICON_INFORMATION, parent=self) except urllib.HTTPError, detail: wx.MessageBox( _("The server said:\n%s\nRequesting the %s resource") % (detail, dlg.GetValue()), _("Remote server error"), style=wx.ICON_INFORMATION, parent=self) except (urllib.URLError, ValueError), detail: wx.MessageBox(_("Cannot open %s, reason %s") % (dlg.GetValue(), detail), parent=self)
def FillinSingleCandidatesStep(self): """ Look for cells with only 1 candidate and fill them in. Updates the candidates after finished """ self.ClearHighlights() dups = sd.FindDuplicates(self.currBoard) if sd.CheckValid(dups): prevBoard = deepcopy(self.currBoard) changed, self.currBoard, self.candBoard = sd.FillSingleCandidates( self.currBoard, self.candBoard) if changed: self.UpdateChangedCells(prevBoard) dups = sd.FindDuplicates(self.currBoard) if not sd.CheckValid(dups): print('Invalid') self.ShowInvalidCells(dups)
def IterativeDFS(initial_state): global COUNT, BACKLINKS OPEN = [initial_state] CLOSED = [] BACKLINKS[Problem.HASHCODE(initial_state)] = -1 while OPEN != []: S = OPEN[0] del OPEN[0] CLOSED.append(S) if Problem.GOAL_TEST(S): print(Problem.GOAL_MESSAGE_FUNCTION(S)) backtrace(S) return COUNT += 1 if (COUNT % 32) == 0: print(".", end="") if (COUNT % 128) == 0: print("COUNT = " + str(COUNT)) print("len(OPEN)=" + str(len(OPEN))) print("len(CLOSED)=" + str(len(CLOSED))) L = [] for op in Problem.OPERATORS: #Optionally uncomment the following when debugging #a new problem formulation. #print("Trying operator: "+op.name) if op.precond(S): new_state = op.state_transf(S) if not occurs_in(new_state, CLOSED): L.append(new_state) BACKLINKS[Problem.HASHCODE(new_state)] = S #Uncomment for debugging: #print(Problem.DESCRIBE_STATE(new_state)) for s2 in L: for i in range(len(OPEN)): if Problem.DEEP_EQUALS(s2, OPEN[i]): del OPEN[i] break OPEN = L + OPEN
def click(self, frame): if self.boutons[0].isCursorInRange( ) or self.boutons[1].isCursorInRange( ) or self.boutons[2].isCursorInRange( ) or self.boutons[3].isCursorInRange( ) or self.boutons[4].isCursorInRange( ) or self.boutons[5].isCursorInRange( ) or self.boutons[6].isCursorInRange( ): # Si un bouton est pressé et que ce nest pas le bouton "Quitter" self.data.soundSystem.playSound("Clique") if self.boutons[0].isCursorInRange( ): # Si le bouton "Sudoku" est pressé # Lancement du Sudoku self.data.partie = Sudoku.PartieG(frame, self.data) elif self.boutons[1].isCursorInRange( ): # Si le bouton "Loto" est pressé # Lancement du Loto self.data.setEtat("Loto_Choose") self.data.partie = LTO.Loto_Party(frame, self.data) elif self.boutons[2].isCursorInRange( ): # Si le bouton "Bataille Navale" est pressé # Lancement de la Bataille Navale self.data.partie = BatailleNavale.GameBN(self.data) self.data.setEtat("BN_Place") self.data.partie.draw(frame, da.Data.menus[self.data.etat]) elif self.boutons[3].isCursorInRange( ): # Si le bouton "Poker" est pressé # Lancement du Poker #self.data.partie = pk.Jeu() poker.start(frame) self.draw(frame) elif self.boutons[4].isCursorInRange( ): # Si le bouton "Options" est pressé # Lancement des options da.Data.menus[1].readCfg() self.data.setEtat("options") self.data.getCurrentMenu().draw(frame) elif self.boutons[5].isCursorInRange( ): # Si le bouton "Profil" est pressé # Lancement du profil self.data.setEtat("Profil_Main") elif self.boutons[6].isCursorInRange( ): # Si le bouton "Classements" est pressé # Lancement des classements self.data.setEtat("Classements") self.data.getCurrentMenu().draw(frame) elif self.boutons[7].isCursorInRange( ): # Si le bouton "Quitter" est pressé # On quitte le jeu if self.data.sound_active: self.data.soundSystem.playSound("byebye") sleepTime = 3 if sleepTime > 0: time.sleep(sleepTime) self.data.fin = True pass
def read_grid(digits): grid = [] grid_info = [] for digit in digits: digit_gray = cv2.cvtColor(digit, cv2.COLOR_BGR2GRAY) processed = preprocessing(digit_gray) contour = Sudoku.find_contours(processed) pom = processed.copy() pom = cv2.cvtColor(pom, cv2.COLOR_GRAY2RGB) if len(contour) > 0: x, y, w, h = cv2.boundingRect(contour) #cv2.rectangle(pom, (x, y), (x + w, y + h), (0, 255, 0), 1) size = w * h / (len(digit) * len(digit[0])) #print(size) #plt.imshow(pom) #plt.show() if size > 0.1 and size < 0.9: #print(size) box = bounding_box(contour) #cv2.rectangle(pom, (box[0][0], box[0][1]), (box[1][0], box[1][1]), (0, 255, 0), 1); #plt.imshow(pom) #plt.show() cropped_digit = processed[box[0][1]:box[1][1], box[0][0]:box[1][0]] black_canvas = generate_black_canvas(28, 28) rows = len(cropped_digit) columns = len(cropped_digit[0]) columns = int(20 / rows * columns) rows = 20 cropped_digit = cv2.resize(cropped_digit, (columns, rows)) x1 = int((28 - rows) / 2) x2 = int((28 - rows) / 2) + rows y1 = int((28 - columns) / 2) y2 = int((28 - columns) / 2) + columns black_canvas[x1:x2, y1:y2] = cropped_digit black_canvas = 1. * (np.array(black_canvas) / 255 > 0.1) grid_info.append(1) grid.append(black_canvas) #plt.imshow(black_canvas, cmap='gray') #plt.show() else: grid_info.append(0) else: grid_info.append(0) grid = np.asarray(grid) digits = grid.reshape((grid.shape[0], 28, 28, 1)).astype('float32') return digits, grid_info
def main(): while (True): print("Commands: ") print("0 - Exit") print("1 - Sudoku") print("2 - Cryptarithmetic") print("3 - Geometric forms") cmd = int(input("Enter command: ")) #try: if (cmd == 0): break elif (cmd == 1): Sudoku.main() elif (cmd == 2): Cryptarithmetic.main() elif (cmd == 3): Geometric.main() else: print("Invalid command")
def generate_(self, generate, subs): if generate: #Handles all generate request. quantity = self.request.get("quantity") if not quantity.isdigit( ) or quantity < 0: #Makes sure valid quantity is entered. subs["q_error"] = "Invalid quantity" return response = Sudoku.generate(quantity) for number in range( 0, 81): #Converts from python list to table format. subs[str(number + 1)] = response[Sudoku.boxes[number]]
def bruteForce(puzzle): if Sudoku.checkFilled(puzzle)[0]: print 'Filled a puzzle' if Sudoku.checkCorrect(puzzle)[0]: return puzzle else: spot = Sudoku.checkFilled(puzzle)[1][0] for num in range(1, len(puzzle) + 1): # Check that the number can go here valid = True for i in range(len(puzzle)): if puzzle[spot[0]][i] == num or puzzle[i][spot[1]] == num: valid = False if valid: puzzle[spot[0]][spot[1]] = num ret = bruteForce(puzzle) if ret: return ret puzzle[spot[0]][spot[1]] = 0
class TestWriterFunctions(unittest.TestCase): def setUp(self): #set up board self.sudoku=Sudoku() board_path="test_boards/test1.txt" self.sudoku.configure_board(board_path) self.board=self.sudoku.board #assert value on board #change board #write board #open board #assert value has changed def test_test1(self): pass
def main(self): for line in self.file: char_list = [] for c in line[0:9]: char_list.append(c) self.puzzle.append(char_list) dlx = DLX(self.puzzle) if dlx.solve(): self.puzzle = dlx.get_puzzle() self.str_list = [] for m in self.puzzle: print "".join(m) self.str_list.append("".join(m)) self.puzzle = self.str_list if Sudoku.check_matrix(self): print "solved" else: print "not a valid puzzle"
from bs4 import BeautifulSoup def pData(data): strBoard = "" for i in range(0,81): print(data[i],end=" ") if i//9 == 0: print("\n") return strBoard r = urllib.request.urlopen("http://view.websudoku.com/?level=1") soup = BeautifulSoup(str(r.read()), 'html.parser') bData = [] for inp in soup.find_all('input'): sinp = str(inp) if 'id=\"f' in sinp: if 'readonly' in sinp: bData += [str(inp['value'])] else: bData += ['X'] print(pData(Sudoku.board_Src_External(bData)))
def setUp(self): #set up board self.sudoku=Sudoku() board_path="test_boards/test1.txt" self.sudoku.configure_board(board_path) self.board=self.sudoku.board
shouldPo = ('-po' in sys.argv) shouldPs = not ('-nops' in sys.argv) runStats = ('-stats' in sys.argv) gameBoard = BoardInterpreter.boardFromFile(boardFile) if shouldPo: print 'Solving:' print gameBoard print ' ' bookkeeping.setupStatusLine() bookkeeping.algorithmStarted() solution = Sudoku.solve(gameBoard) timeToSolve = bookkeeping.algorithmEnded() bookkeeping.teardownStatusLine() if shouldPs: print 'Solution:' print (solution if solution is not None else 'No solution.') print ' ' if runStats: print ' Steps (Boards Surmised):', bookkeeping.boardsCreated() print ' Bad Boards Backtracked:', bookkeeping.impossibleBoards print ' Boards Pruned (Fwd. Check):', bookkeeping.caughtByFwdcheck() print "Boards Pruned (Arc Const'y):", bookkeeping.caughtByAc3() if timeToSolve > 1 or ('-time' in sys.argv):