def __init__(self): self._level = 0 self._solver = sudoku_solver.SudokuSolver() self._max_solver = sudoku_solver.SudokuSolver(randomize_type='max') self._min_solver = sudoku_solver.SudokuSolver(randomize_type='min') self._sudoku_map = { 'EASY': [], 'MEDIUM': [], 'HARD': [], 'CHALLENGER': [] }
def T_test_find_hidden_single(self): sparse_empty_0_ = [[[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []]] s0 = ss.SudokuSolver() empty = [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] all_possibles = [[[num for num in range(1, 10)] for column in range(9)] for row in range(9)] s0.give_initial_digits(empty) s0.find_hidden_single() cell_array = grids_to_cell_array(empty, all_possibles) self.assertEqual(s0.grid, cell_array) s0 = ss.SudokuSolver() five_ = [[1, 2, 3, 4, 0, 0, 6, 9, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 5, 5, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] fiveH = [[1, 2, 3, 4, 0, 0, 6, 9, 5], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 5, 5, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] #cell has right possibles before find_hidden_single #house has right possibles s0.give_initial_digits(five_) s0.find_hidden_single() self.assertEqual(s0.grid, fiveH)
def test_update_grid_empty(self): # get this to work from setUp empty = [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] all_possibles = [[[num for num in range(1, 10)] for column in range(9)] for row in range(9)] s1 = ss.SudokuSolver() s1.give_initial_digits(empty) empty_cells = grids_to_cell_array(empty, all_possibles) print(empty_cells) self.assertEqual(s1.grid, empty_cells) self.assertTrue(s1.rows[0][0] is s1.columns[0][0]) self.assertTrue(s1.rows[0][0] is s1.squares[0][0]) self.assertTrue(s1.rows[1][1] is s1.columns[1][1]) self.assertTrue(s1.rows[4][4] is s1.squares[4][4])
def _solved_puzzle_image(self, stringified_puzzle): solver = sudoku_solver.SudokuSolver() solution = '' solution = solver.solve(stringified_puzzle) image_solution = self.parser.draw_solution(solution) image_solution = self.parser.convert_to_jpeg(image_solution) return image_solution
def main(): sudoku = sio.parse_sudoku("mesi.sud") solutions = [] solver = ss.SudokuSolver() solver(sudoku, solutions) sio.write_solution_to_file(solutions, "mesi-solution.txt")
def test_update_grid_hard(self): hard_one = [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 4, 9, 3, 0, 0, 2, 1, 0], [5, 1, 0, 0, 0, 9, 0, 0, 0], [0, 3, 1, 9, 0, 4, 0, 7, 6], [0, 0, 0, 0, 7, 0, 0, 0, 0], [0, 8, 5, 1, 0, 3, 0, 2, 9], [3, 5, 0, 0, 0, 1, 0, 0, 0], [0, 7, 8, 4, 0, 0, 9, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] s1 = ss.SudokuSolver() self.assertTrue(s1.rows[0][0] is s1.columns[0][0]) self.assertTrue(s1.rows[0][0] is s1.squares[0][0]) self.assertTrue(s1.rows[1][1] is s1.columns[1][1]) self.assertTrue(s1.rows[4][4] is s1.squares[4][4]) s1.give_initial_digits(hard_one) hard_one_possibles = [[[2, 6, 7, 8], [2, 6], [2, 3, 6, 7], [2, 5, 6, 7, 8], [1, 2, 4, 5, 6, 8], [2, 5, 6, 7, 8], [3, 4, 5, 6, 7, 8], [4, 5, 6, 8, 9], [3, 4, 5, 7, 8]], [[6, 7, 8], [], [], [], [5, 6, 8], [5, 6, 7, 8], [], [], [5, 7, 8]], [[], [], [2, 3, 6, 7], [2, 6, 7, 8], [2, 4, 6, 8], [], [3, 4, 6, 7, 8], [4, 6, 8], [3, 4, 7, 8]], [[2], [], [], [], [2, 5, 8], [], [5, 8], [], []], [[2, 4, 6, 9], [2, 6, 9], [2, 4, 6], [2, 5, 6, 8], [], [2, 5, 6, 8], [1, 3, 4, 5, 8], [4, 5, 8], [1, 3, 4, 5, 8]], [[4, 6, 7], [], [], [], [6], [], [4], [], []], [[], [], [2, 4, 6], [2, 6, 7, 8], [2, 6, 8, 9], [], [4, 6, 7, 8], [4, 6, 8], [2, 4, 7, 8]], [[1, 2, 6], [], [], [], [2, 5, 6], [2, 5, 6], [], [], [1, 2, 5]], [[1, 2, 4, 6, 9], [2, 6, 9], [2, 4, 6], [2, 5, 6, 7, 8], [2, 3, 5, 6, 8, 9], [2, 5, 6, 7, 8], [1, 4, 5, 6, 7, 8], [4, 5, 6, 8], [1, 2, 4, 5, 7, 8]]] # for rowIndex, row in enumerate(s1.grid): # for columnIndex, cell in enumerate(row): # self.assertEqual(cell.possibes, hard_one_possibles[rowIndex][columnIndex]) hard_one_cells = grids_to_cell_array(hard_one, hard_one_possibles) self.assertEqual(s1.grid, hard_one_cells) self.assertTrue(s1.rows[0][0] is s1.columns[0][0]) self.assertTrue(s1.rows[0][0] is s1.squares[0][0]) self.assertTrue(s1.rows[1][1] is s1.columns[1][1]) self.assertTrue(s1.rows[4][4] is s1.squares[4][4]) self.assertTrue(s1.rows[1][2] is s1.columns[2][1]) self.assertTrue(s1.squares[7][2] is s1.columns[5][6])
def test_generator(generator, level): sudoku = generator.get_sudoku(level=level) passed = True actual_level = generator.get_sudoku_level(sudoku) if level != actual_level: print('Level does not match. Expected {}. Actual {}'.format( level, actual_level)) passed = False solver = sudoku_solver.SudokuSolver() solution = solver.solve(sudoku) if not solution: print('Can not solve the generated sudoku.') passed = False if not passed: raise RuntimeError('Test for {} level failed.'.format(level))
def get(self): """Simplistic solver API""" puzzle = self.request.get('puzzle') if puzzle: solver = sudoku_solver.SudokuSolver() try: solution = solver.solve(puzzle) except (sudoku_solver.ContradictionError, ValueError) as e: logging.debug(e) self.response.write( '%s Puzzle: %s.' % (str(e), puzzle)) return self.response.headers['Content-Type'] = 'text/plain' self.response.write(solution) else: self.response.write('No puzzle data')
def __init__(self, stdscr): self.stdscr = stdscr self.height = 18 self.width = 36 self.curr_row = 4 self.curr_col = 4 self.curr_color = 1 self.message = None self.confirm = None self.mouse_x = None self.mouse_y = None self.level = 'Easy' self.sudoku = sudoku_data.SudokuData() self.solver = sudoku_solver.SudokuSolver() self.generator = sudoku_generator.SudokuGenerator() self._setup_colors() self.data_file = '/tmp/magic_sudoku.data' self.changes = [] self.redo_changes = []
def test_solver(path, type): if type == 'partial': partial = True simple = False elif type == 'simple': partial = False simple = True else: partial = False simple = False for file_name in os.listdir(path): full_name = os.path.join(path, file_name) sudoku, expected_solution = read_data_file(full_name) original = sudoku_data.SudokuData() original.copy(sudoku) solution = sudoku_solver.SudokuSolver().solve(sudoku, partial=partial, simple=simple) compare_solutions(full_name, solution, expected_solution) compare_sudoku(full_name, sudoku, original, solution) print('Tests in {!r} with type {!r} passed.'.format(path, type))
def test_find_naked_single(self): all_possibles = [[[num for num in range(1, 10)] for column in range(9)] for row in range(9)] sparse_empty_0_ = [[[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []]] s0 = ss.SudokuSolver() s0.possiblesByCell = sparse_empty_0_ empty = [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] s0.find_naked_single() cell_array = grids_to_cell_array(empty, all_possibles) self.assertEqual(s0.grid, cell_array) sparse_empty_1_ = [[[5], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []]] s1 = ss.SudokuSolver() s1.possiblesByCell = sparse_empty_1_ just5 = [[5, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] s1.find_naked_single() cell_array = grids_to_cell_array(just5, sparse_empty_1_) self.assertEqual(s1.grid, cell_array) sparse_empty_2_ = [[[], [], [], [], [], [], [3, 6, 7], [], []], [[], [], [7], [], [], [1, 2, 8], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [8], [], []], [[], [3], [], [], [], [4, 7, 8, 9], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [2, 4, 6], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], [9]]] s2 = ss.SudokuSolver() s2.possiblesByCell = sparse_empty_2_ justN = [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 7, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 8, 0, 0], [0, 3, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 9]] s2.find_naked_single() self.assertEqual(s2.grid, justN)
def solve(self): solver = sudoku_solver.SudokuSolver(self.board) self.solvedboard = solver.solved print(self.solvedboard)
def run(input_img): # open the image #img = cv2.imread(filename) #peek("1",img) # resize all input images to the same size for convenience img = cv2.resize(input_img,(900,900)) img2 = np.copy(img) # convert img to grayscale gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #peek("2",gray) # blur the image to smooth out noise, even when they look fine they have noise sometimes smooth = cv2.GaussianBlur(gray,(3,3),0) #peek("3",smooth) # adaptive threshold thresh = cv2.adaptiveThreshold(smooth,255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11,2) thresh2 = cv2.adaptiveThreshold(smooth,255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11,2) #peek("4",thresh) # find contour lines - after this somehow the thresh img is changed, which is why we have thresh2 _image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #cv2.drawContours(img, contours, -1, (0,255,0), 1) #peek("3",img) # idx = 0 # The index of the contour that surrounds your object # mask = np.zeros_like(gray) # Create mask where white is what we want, black otherwise # cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask # out = np.zeros_like(gray) # Extract out the object and place into output image # # out[mask == 255] = img[mask == 255] # # # Show the output image # cv2.imshow('Output', out) # cv2.waitKey(0) # cv2.destroyAllWindows() selected_contours = [] for cnt in contours: if cv2.contourArea(cnt) > 5000 and cv2.contourArea(cnt) < 15000: #trying to isolate actual grids, should work if all images are same size x,y,w,h = cv2.boundingRect(cnt) selected_contours.append((x,y,w,h)) #count if there's 81 here if len(selected_contours) != 81: print("ERROR: wrong number of contours somehow") sys.exit() #sort contours by x,y, (starting in top left) selected_contours = sorted(selected_contours, key=operator.itemgetter(1,0)) contour_values = [] puzzle = [[],[],[],[],[],[],[],[],[]] row_count = 0 #cut out and save idx =0 for x,y,w,h in selected_contours: #if cv2.contourArea(cnt) > 10000 and cv2.contourArea(cnt) < 20000:#trying to isolate actual grids HOPEFULLY EXACTLY 81 idx += 1 #x,y,w,h = cv2.boundingRect(cnt) roi=thresh2[y+5:y+h-5,x+5:x+w-5] #used to be img (which is not pure black/white) #also cropping black edges off # cv2.imshow('ROI',roi) # cv2.waitKey(0) # cv2.imwrite("grid_pics/" + str(idx) + '.jpg', roi) #SAVING PICS FOR ANALYSIS #print(str(idx) + ":" + image_file_to_string("grid_pics/" + str(idx) + '.jpg')) #cv2.rectangle(img,(x,y),(x+w-2,y+h-2),(0,255,0),1) #get the number using my FANCY OCR #num = henry_ocr.get_number_from_img("grid_pics/" + str(idx) + '.jpg') num = henry_ocr.get_number_from_img(roi) #print(str(idx) + ":" + num, x, y)#, cv2.contourArea(cnt)) #save number or blank into next slot of board data structure if num: puzzle[row_count / 9].append(num) cv2.putText(img2,num,(x+w/8,y+h/3),0,1,(255,0,0),2) else: puzzle[row_count / 9].append("x") row_count += 1 contour_values.append((x,y,w,h,num)) #this is just used for writing solution to img #peek("4", img) print('\n'.join([''.join(['{:4}'.format(item) for item in row]) for row in puzzle])) # cv2.imshow('img',img) # cv2.waitKey(0) #################TIME TO SOLVE########################### #["..9748...","7........",".2.1.9...","..7...24.",".64.1.59.",".98...3..","...8.3.2.","........6","...2759.."] #[[],[],[],[],[],[],[],[],[]] #probably helpful if this returns True/False on success/failure s = sudoku_solver.SudokuSolver() s.solveSudoku(puzzle) print "Count:" ,s.count print "\n*********************\n" print('\n'.join([''.join(['{:4}'.format(item) for item in row]) for row in puzzle])) #print contour_values #PRINT SOLUTION #we need to know which boxes were empty (x), and their coordinates so we can write the new value i = 0 for x,y,w,h,num in contour_values: if num == "": #draw at x,y, using puzzle[i/9][i%9] cv2.putText(img,str(puzzle[i/9][i%9]),(x+w/4,y+h * 3/4),0,3,(0,255,0),5) #cv2.putText(out,string,(x,y+h),0,1,(0,255,0)) i += 1 #cv2.imwrite("static/output2.png", img) #cv2.imshow('FINAL',img) #cv2.waitKey(0) return img2, img
import sudoku_parser import sudoku_solver from cv2 import imshow, waitKey from sys import argv sudoku = sudoku_parser.SudokuParser() solver = sudoku_solver.SudokuSolver() if not argv[1]: raise IndexError puzzle = sudoku.parse(argv[1]) solution = solver.solve(puzzle) sudoku.draw_solution(solution) imshow('result', sudoku.resized_largest_square) waitKey(0)