from utilities import * sudoku1 = ["5", "3", ".", ".", "7", ".", ".", ".", ".", "6", ".", ".", "1", "9", "5", ".", ".", ".", ".", "9", "8", ".", ".", ".", ".", "6", ".", "8", ".", ".", ".", "6", ".", ".", ".", "3", "4", ".", ".", "8", ".", "3", ".", ".", "1", "7", ".", ".", ".", "2", ".", ".", ".", "6", ".", "6", ".", ".", ".", ".", "2", "8", ".", ".", ".", ".", "4", "1", "9", ".", ".", "5", ".", ".", ".", ".", "8", ".", ".", "7", "9"] """ General note: we have decided to represent a sudoku board as a list of 81 values. Each value is a character, that can be a digit from 1 to 9, or a dot (".") to signify a blank spot. The values are listed in left-to-right, top-to-bottom order. It is our responsibility, in the rest of the code, to respect this representation decision. At the same time, it is good programming practice to make the rest of the code as independent of this decision as possible. A good programming guideline is that, if at any point we decide to change the representation, only a few changes should be necessary in the rest of the code. In order to ensure that our code as independent of the representation choice as possible, we will ensure that the ONLY functions that depend on this decision are the following functions: - check_sudoku_validity(sudoku) - compute_sudoku_position(row, col) - get_sudoku_value(sudoku, row, col) - set_sudoku_value(sudoku, row, col, value) - legal_sudoku_value - create_empty_sudoku - sudoku_deep_copy Furthermore, the rest of the code, when dealing with a sudoku, is only allowed to use the above functions to read information from a sudoku, or write information to a sudoku. """ """ input: a python object (can be anything, int, float, list, string...) output: True if the python object is a valid sudoku board, that follows our convention on how a sudoku board can be represented. """ def check_sudoku_validity(sudoku): if not(type(sudoku) is list): return False if len(sudoku) != 81: return False for entry in sudoku: if not(entry in "123456789."): return False return True """ inputs: row, col specify positions on a sudoku board. legal values for row and col are integers from 1 to 9 output: the position on the sudoku board (which is represented as a list) that stores the value for that row and col """ def compute_sudoku_position(row, col): position = (row-1)*9 + col-1 return position """ inputs: sudoku board, row and col output: the value stored in the sudoku board, for that row and col. Rows and columns are numbered from 1 to 9. """ def get_sudoku_value(sudoku, row, col): position = compute_sudoku_position(row, col) result = sudoku[position] return result """ inputs: a sudoku board output: a new sudoku board, that is a deep copy of the input (so that changing the output sudoku will have no effect on the input sudoku) """ def sudoku_deep_copy(in_sudoku): out_sudoku = in_sudoku[:] return out_sudoku """ inputs: sudoku board, row, col, value output: a new sudoku board, that is the same as the original sudoku board, except that the new board contains the specified value at the position specified by row and col """ def set_sudoku_value(in_sudoku, row, col, value): out_sudoku = sudoku_deep_copy(in_sudoku) position = compute_sudoku_position(row, col) out_sudoku[position] = value return out_sudoku """ create_empty_sudoku takes no input, and returns an empty sudoku board. """ def create_empty_sudoku(): sudoku_string = '.' * 81 result = list(sudoku_string) return result def legal_sudoku_value(value): if value in "123456789.": return True else: return False """ NOTE: All functions after this point should be independent of the specific sudoku representation """ """ This function prints a sudoku board. """ def print_sudoku(sudoku): string_version = sudoku_to_string(sudoku) print string_version """ This function converts a sudoku board into a string. This string can later be used for printing, or for saving to a file. The goal is that this string should be easy to read when printed. """ def sudoku_to_string(sudoku): result = "" for row in range(1, 10): result = result + get_sudoku_value(sudoku, row, 1) result = result + get_sudoku_value(sudoku, row, 2) result = result + get_sudoku_value(sudoku, row, 3) result = result + " " result = result + get_sudoku_value(sudoku, row, 4) result = result + get_sudoku_value(sudoku, row, 5) result = result + get_sudoku_value(sudoku, row, 6) result = result + " " result = result + get_sudoku_value(sudoku, row, 7) result = result + get_sudoku_value(sudoku, row, 8) result = result + get_sudoku_value(sudoku, row, 9) result = result + "\n" if (row == 3) or (row == 6): result = result + "\n" return result """ Saves a sudoku board into a file. """ def save_sudoku(sudoku, filename): fp = open(filename, "w") string_version = sudoku_to_string(sudoku) fp.write(string_version) fp.close() """ input: a sudoku board output: [row, col, value], a list of three items, specifying the row, column and value for the user's next move. """ def input_sudoku_move(): print "enter row, col, and value, on separate lines." while(True): row = input_integer("enter the row: ") if (row < 1) or (row > 9): print "The row must be between 1 and 9" else: break while(True): col = input_integer("enter the col: ") if (col < 1) or (col > 9): print "The col must be between 1 and 9" else: break while(True): value = raw_input("enter the value: ") if (legal_sudoku_value(value) == False): print value, "is not a legal sudoku value" else: break return [row, col, value] """ input: a sudoku board output: a new sudoku board, that is identical to the input board, except for one position. The user is asked to specify the position, and the new value for that position """ def make_move_interactively(in_sudoku): [row, col, value] = input_sudoku_move() out_sudoku = set_sudoku_value(in_sudoku, row, col, value) return out_sudoku """ We want a function that checks, at some specific position on the board, which numbers are legal values, using some simple rules """ def legal_position_numbers(sudoku, row, col): row_values = sudoku_row_values(sudoku, row) col_values = sudoku_col_values(sudoku, col) block_values = sudoku_block_values(sudoku, row, col) result = list("123456789") result = remove_values(result, row_values) result = remove_values(result, col_values) result = remove_values(result, block_values) return result """ inputs: a sudoku board, and a row (from 1 to 9) output: the list of numbers showing up on that row """ def sudoku_row_values(sudoku, row): # create an empty list called "result" result = [] # for each column, from 1 to 9: for col in range(1, 10): # get the value at position (row, col) value = get_sudoku_value(sudoku, row, col) # if that value is not a dot, add it to result if value != ".": result.append(value) return result """ inputs: a sudoku board, and a col (from 1 to 9) output: the list of numbers showing up on that col """ def sudoku_col_values(sudoku, col): # create an empty list called "result" result = [] # for each column, from 1 to 9: for row in range(1, 10): # get the value at position (row, col) value = get_sudoku_value(sudoku, row, col) # if that value is not a dot, add it to result if value != ".": result.append(value) return result """ inputs: a sudoku board, and a row and col (from 1 to 9) output: the list of numbers showing up on the 3x3 block that (row, col) belongs to """ def sudoku_block_values(sudoku, row, col): start_row = index_to_block_start(row) start_col = index_to_block_start(col) result = [] for row_index in range(start_row, start_row + 3): for col_index in range(start_col, start_col + 3): value = get_sudoku_value(sudoku, row_index, col_index) if (value != "."): result.append(value) return result def index_to_block_start(index): result = ((index-1) / 3) * 3 + 1 return result def index_to_block_start2(index): if (index == 1): return 1 elif (index == 2): return 1 elif (index == 3): return 1 elif (index == 4): return 4 elif (index == 5): return 4 elif (index == 6): return 4 elif (index == 7): return 7 elif (index == 8): return 7 elif (index == 9): return 7 """ inputs: initial_list is a list of values. values_to_remove is a list of values we want to remove from initial_list output: a list that is similar to initial_list, except that it does not contain any value from values_to_remove """ def remove_values2(initial_list, values_to_remove): result = [] for i in initial_list: should_append = True for x in values_to_remove: if (i == x): should_append = False if should_append == True: result.append(i) return result def remove_values(initial_list, values_to_remove): result = [] for i in initial_list: if not(i in values_to_remove): result.append(i) return result