Untitled
unknown
plain_text
2 years ago
4.6 kB
4
Indexable
#!/usr/bin/env python # coding:utf-8 """ Each sudoku board is represented as a dictionary with string keys and int values. e.g. my_board['A1'] = 8 """ import sys import time ROW = "ABCDEFGHI" COL = "123456789" def print_board(board): """Helper function to print board in a square.""" print("-----------------") for r in ROW: row = '' for c in COL: row += (str(board[r + c]) + " ") print(row) def board_to_string(board): """Helper function to convert board dictionary to string for writing.""" ordered_vals = [] for r in ROW: for c in COL: ordered_vals.append(str(board[r + c])) return ''.join(ordered_vals) def backtracking(board): """Takes a board and returns solved board.""" r, c = get_mrv(board) if r is None: return board for val in range(1, 10): if valid(board, val, r, c): if not forward_checking(board, val, r, c): continue board[ROW[r] + COL[c]] = val solved_board = backtracking(board) if solved_board: return solved_board board[ROW[r] + COL[c]] = 0 return None def get_mrv(board): mrv = 9 r, c = None, None for i in range(9): for j in range(9): if board[ROW[i] + COL[j]] == 0: rv_count = get_rv_count(board, i, j) if rv_count < mrv: mrv = rv_count r, c = i, j return r, c def get_rv_count(board, r, c): rv_count = 0 for val in range(1, 10): if valid(board, val, r, c): rv_count += 1 return rv_count def valid(board, val, r, c): # check column constraints for i in range(9): if board[ROW[i] + COL[c]] == val: return False # check row constraints for j in range(9): if board[ROW[r] + COL[j]] == val: return False # check box constraints box_row = r // 3 box_col = c // 3 for i in range(3): for j in range(3): if board[ROW[box_row * 3 + i] + COL[box_col * 3 + j]] == val: return False return True def forward_checking(board, val, r, c): board[ROW[r] + COL[c]] = val for i in range(9): for j in range(9): if board[ROW[i] + COL[j]] == 0 and get_rv_count(board, i, j) == 0: board[ROW[r] + COL[c]] = 0 return False board[ROW[r] + COL[c]] = 0 return True if __name__ == '__main__': start_time = time.time() if len(sys.argv) > 1: # Running sudoku solver with one board $python3 sudoku.py <input_string>. print(sys.argv[1]) # Parse boards to dict representation, scanning board L to R, Up to Down board = {ROW[r] + COL[c]: int(sys.argv[1][9 * r + c]) for r in range(9) for c in range(9)} solved_board = backtracking(board) # Write board to file out_filename = 'output.txt' outfile = open(out_filename, "w") outfile.write(board_to_string(solved_board)) outfile.write('\n') else: # Running sudoku solver for boards in sudokus_start.txt $python3 sudoku.py # Read boards from source. src_filename = 'sudokus_start.txt' try: srcfile = open(src_filename, "r") sudoku_list = srcfile.read() except: print("Error reading the sudoku file %s" % src_filename) exit() # Setup output file out_filename = 'output.txt' outfile = open(out_filename, "w") # Solve each board using backtracking for line in sudoku_list.split("\n"): if len(line) < 9: continue # Parse boards to dict representation, scanning board L to R, Up to Down board = {ROW[r] + COL[c]: int(line[9 * r + c]) for r in range(9) for c in range(9)} # Print starting board. TODO: Comment this out when timing runs. print_board(board) # Solve with backtracking solved_board = backtracking(board) # Print solved board. TODO: Comment this out when timing runs. print_board(solved_board) # Write board to file outfile.write(board_to_string(solved_board)) outfile.write('\n') print("Finishing all boards in file.") end_time = time.time() print("Program completed in %.3f second(s)" % (end_time - start_time))
Editor is loading...