def sudoku_backtracking(sudoku): variables.counter=0 #Initialize the Stack stack = Stack(); #Find where to start initRow, initCol = get_initial_point(sudoku) #Create the initial Board and add it to stack initBoard = Board(Copy_Board(sudoku),initRow,initCol) stack.put(initBoard) #Iterate for as long as the stack is full while not stack.empty(): variables.counter+= 1 #Get current information currBoard = stack.get() currRow = currBoard.currRow currCol = currBoard.currCol if currRow > 8 or currCol > 8: continue #Get the next point nexRow, nexCol = get_next_square(currRow, currCol) #If square is already filled, move forward if currBoard.sudoku[currRow][currCol] != 0: stack.put(Board(currBoard.sudoku, nexRow, nexCol)) #If square is empty, look for which values to fill it for newLabel in range(1,10): if common.can_yx_be_z(currBoard.sudoku, currRow, currCol, newLabel): newB = Copy_Board(currBoard.sudoku) newB[currRow][currCol] = newLabel if StopCheck(newB): break stack.put(Board(newB, nexRow, nexCol)) if StopCheck(newB): break for row in range(9): for col in range(9): sudoku[row][col] = newB[row][col] return variables.counter
def helper_backtracking(sudoku, variables): variables.counter += 1 #start position (y, x) = (row, col) (y, x) = (0, 0) #if board is complete, return True and exit recursion if (chk_result(sudoku)): return True #check full board for y in range(9): for x in range(9): if sudoku[y][x] == 0: #if move is empty for z in range(1, 10): #check all possible values 1-9 if can_yx_be_z(sudoku, y, x, z): #if no conflict in row/col/box sudoku[y][x] = z #play the move result = helper_backtracking( sudoku, variables ) #recursively make moves and check validity of moves if result: #if all resulting moves worked, return True and backtrack all the way out of recursion return True else: sudoku[y][ x] = 0 #if playing move z didn't work, set it back to 0 and try next iteration of z if sudoku[y][ x] == 0: #if none of the z values worked, this board not solveable. exit with return False return False
def helper_fwdchk(sudoku, domain): variables.counter += 1 if (chk_result(sudoku)): return True for y in range(9): for x in range(9): if (sudoku[y][x] == 0): for z in range(1, 10): if (common.can_yx_be_z(sudoku, y, x, (z))): domain_update = remove_z_from_dneighbors( domain, y, x, z ) #before making the play of z at position (y,x), clear from domain of this position's neighbors if (check_domain_notempty(domain_update) ): #making sure there is no empty domain sudoku[y][x] = (z) #play the move result = helper_fwdchk(sudoku, domain_update) if (result): return result else: sudoku[y][x] = 0 if sudoku[y][x] == 0: return False
def get_domain_unassigned_variables(unassigned_variables, sudoku): for i in range(0, len(unassigned_variables)): var = unassigned_variables[i] x = [] for j in order_domain_values: if common.can_yx_be_z(sudoku, var[0], var[1], j): x.append(j) unassigned_variables[i].append(x)
def Find_Possible_Entries(row, column, sudoku): returnArr = [] if sudoku[row][column] != 0: return returnArr for num in range(1,10): if common.can_yx_be_z(sudoku, row, column, num): returnArr.append(num) if len(returnArr) == 0: return None return returnArr
def chk_result(sudoku): result = True for y in range(9): for x in range(9): value = sudoku[y][x] sudoku[y][x] = 0 if (value != 0 and common.can_yx_be_z(sudoku, y, x, value)): sudoku[y][x] = value else: result = False sudoku[y][x] = value return result
def update_domain(sudoku, var, unassigned_variables): for j in range(len(unassigned_variables)): curr_var = unassigned_variables[j] if ((var[0] == curr_var[0]) or (var[1] == curr_var[1]) or (var[0] / 3 * 3 + var[1] / 3 == curr_var[0] / 3 * 3 + curr_var[1])): for k in curr_var[2]: if not common.can_yx_be_z(sudoku, curr_var[0], curr_var[1], k): curr_var[2].remove(k) if not curr_var[2]: return False return True
def mrv_helper(sudoku): spot_master = {} for y in range(9): for x in range(9): compat = [] for val in range(1, 10): if common.can_yx_be_z(sudoku, y, x, val) and sudoku[y][x] == 0: compat.append(val) if compat != []: spot_master[y, x] = compat return spot_master
def verify_complete(sudoku): for y in range(9): for x in range(9): z = sudoku[y][x] if(z==0): return False sudoku[y][x] = 0 if(z!=0 and common.can_yx_be_z(sudoku,y,x,z)): sudoku[y][x] = z pass else: sudoku[y][x] = z return False return True
def backtracking(sudoku_in): variables.counter += 1 if(verify_complete(sudoku_in)): return True for y in range(9): for x in range(9): if(sudoku_in[y][x]==0): for z in range(9): if(common.can_yx_be_z(sudoku_in,y,x,(z+1))): sudoku_in[y][x] = z+1 result = backtracking(sudoku_in) if(result): return result else: sudoku_in[y][x] = 0 return False
def mrv(sudoku, unassigned_variables): variables.counter += 1 if not unassigned_variables: return True id = get_mrv(sudoku, unassigned_variables) var = copy_list(unassigned_variables[id]) unassigned_variables.pop(id) for val in var[2]: if (common.can_yx_be_z(sudoku, var[0], var[1], val)): sudoku[var[0]][var[1]] = val result = mrv(sudoku, unassigned_variables) if result: return result sudoku[var[0]][var[1]] = 0 unassigned_variables.insert(0, var) return False
def backtracking(sudoku, unassigned_variables): variables.counter += 1 if not unassigned_variables: return True var = unassigned_variables[0] unassigned_variables.pop(0) for i in range(0, len(order_domain_values)): v = order_domain_values[i] if (common.can_yx_be_z(sudoku, var[0], var[1], v)): sudoku[var[0]][var[1]] = v result = backtracking(sudoku, unassigned_variables) if result: return result sudoku[var[0]][var[1]] = 0 unassigned_variables.insert(0, var) return False
def sudoku_forwardchecking(sudoku): variables.counter = 0 domain = [[[0 for v in range(9)] for j in range(9)] for i in range(9)] for i in range(9): for j in range(9): for v in range(1, 10): if common.can_yx_be_z(sudoku, i, j, v): domain[i][j][v - 1] = 1 else: domain[i][j][v - 1] = 0 forward_recur(sudoku, domain) return variables.counter
def check_result(sudoku, show): result = True for y in range(9): v = "" for x in range(9): value = sudoku[y][x] sudoku[y][x] = 0 if (value != 0 and common.can_yx_be_z(sudoku, y, x, value)): v += bcolors.GREEN else: result = False v += bcolors.RED v += str(value) sudoku[y][x] = value if (show): print(v) return result
def backtrack_recur(sudoku): variables.counter += 1 if is_complete(sudoku): return True for i in range(9): for j in range(9): if sudoku[i][j] == 0: for v in range(1, 10): if common.can_yx_be_z(sudoku, i, j, v): sudoku[i][j] = v if backtrack_recur(sudoku): return True sudoku[i][j] = 0 return False
def recursive_forwardtracking(variables, sudoku, domain): """ Recursive function for the forward-tracking function """ # Increase counter variables.counter += 1 # Check if board is complete if check_complete(sudoku): return True # If board not complete - check next step for y in range(SUDOKU_HEIGHT): for x in range(SUDOKU_WIDTH): # Check if a cell is available if check_available(sudoku, y, x): # Check available next step for value in range(1, SUDOKU_WIDTH + 1): # Check cell for constraints if common.can_yx_be_z(sudoku, y, x, value): # Update a copy of the domain new_domain = copy_board(domain.copy()) updated_domain, is_full_domain = update_domain( new_domain, y, x, value) if is_full_domain: # Set cell with value sudoku = set_cell(sudoku, y, x, value) result = recursive_forwardtracking( variables, sudoku, updated_domain) if result: return True else: sudoku = set_cell(sudoku, y, x, AVAILABLE_CELL) if check_available(sudoku, y, x): return False return False
def forwardchecking(sudoku_in,zs_in): variables.counter += 1 if(verify_complete(sudoku_in)): return True for y in range(9): for x in range(9): if(sudoku_in[y][x]==0): for z in range(9): if(common.can_yx_be_z(sudoku_in,y,x,(z+1))): cp_zs = update_zs(zs_in,y,x,(z+1)) if(verify_zs(cp_zs)): sudoku_in[y][x] = (z+1) result = forwardchecking(sudoku_in,cp_zs) if(result): return result else: sudoku_in[y][x] = 0 return False
def recursive_fc(sudoku): done = finished(sudoku) if done: return done # otherwise... # find the next empty location... y, x = findNext(sudoku) solved = False for nval in range(1, 10): canbe = common.can_yx_be_z(sudoku, y, x, nval) if canbe: variables.counter += 1 sudoku[y][x] = nval solved = recursive_fc(sudoku) if solved == False: # reset the changed val to 0 sudoku[y][x] = 0 else: return solved # True return solved
def check_complete(sudoku): """ Checks if the board is complete. If complete, returns True """ for y in range(SUDOKU_HEIGHT): for x in range(SUDOKU_WIDTH): if check_available(sudoku, y, x): return False # Check cell constraints if not (check_available(sudoku, y, x)): value = sudoku[y][x] sudoku = set_cell(sudoku, y, x, AVAILABLE_CELL) if common.can_yx_be_z(sudoku, y, x, value): sudoku = set_cell(sudoku, y, x, value) else: return False return True
def forward_recur(sudoku, domain): variables.counter += 1 # print(variables.counter) if is_complete(sudoku): return True for i in range(9): for j in range(9): if sudoku[i][j] == 0: for v in range(1, 10): if common.can_yx_be_z(sudoku, i, j, v): old_domain = [[j[:] for j in i] for i in domain] sudoku[i][j] = v if update_domain(domain, sudoku, i, j, v): if forward_recur(sudoku, domain): return True sudoku[i][j] = 0 domain = [[j[:] for j in i] for i in old_domain] return False
def recursive_backtracking(variables, sudoku): """ Recursive function for the forward-tracking function """ # Increase counter variables.counter += 1 # Check if board is complete if check_complete(sudoku): return True # If board not complete - check next step for y in range(SUDOKU_HEIGHT): for x in range(SUDOKU_WIDTH): # Check if a cell is available if check_available(sudoku, y, x): # Check available next step for i in range(1, SUDOKU_WIDTH + 1): # Check cell for constraints if common.can_yx_be_z(sudoku, y, x, i): # Copy board and check cell for index new_sudoku = copy_board(sudoku) new_sudoku = set_cell(sudoku, y, x, i) result = recursive_backtracking(variables, new_sudoku) if result: # sudoku = set_cell(sudoku, y, x, i) return True else: sudoku = set_cell(sudoku, y, x, AVAILABLE_CELL) if check_available(sudoku, y, x): return False return False
def helper_fwdchk(sudoku, d, variables): variables.counter += 1 (y, x) = (0, 0) if (chk_result(sudoku)): return True #check full board for y in range(9): for x in range(9): if sudoku[y][x] == 0: #deepcopy domain d_copy = copy_domain(d) for z in range(1, 10): if can_yx_be_z(sudoku, y, x, z): print(f"z = {z} can be played\n") position = (y, x) z_neighbors = build_neighbors(position, sudoku) d = remove_z_from_dneighbors(z_neighbors, d, z) print( f"z = {z}, pos = {(y, x)} and zneighbors after: {z_neighbors}\n" ) if check_domain_notempty(d): sudoku[y][x] = z print(f"entered search tree at z = {z}\n") result = helper_fwdchk(sudoku, d, variables) if result: print(f"result returned true\n") return True else: print(f"resetting z = {z} play\n") sudoku[y][x] = 0 d = copy_domain(d_copy) return False
def get_domain(sudoku, currRow, currCol): returnArr = [] for num in range(1,10): if common.can_yx_be_z(sudoku,currRow, currCol, num): returnArr.append(num) return returnArr
def is_valid(board, spot, value): return common.can_yx_be_z(board, spot[0], spot[1], value)