def test_invalid_move(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', '', ''], ['D', 'C', '', '']]) with self.assertRaises(ValueError): s.move('(2, 2) -> C')
def test_bad_format(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', '', ''], ['D', 'C', '', '']]) with self.assertRaises(ValueError): s.move('2 2 C')
def test_has_unique_solution_doctest() -> None: """Test has_unique_solution on a SudokuPuzzle with a non-unique solution.""" s = SudokuPuzzle(4, [["D", "C", "B", "A"], ["B", "A", "D", "C"], ["C", " ", "A", " "], ["A", " ", "C", " "]], {"A", "B", "C", "D"}) assert s.has_unique_solution() is False
def test_sample(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', '', ''], ['D', 'C', '', '']]) new_s = s.move('(2, 2) -> D') s1 = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', 'D', ''], ['D', 'C', '', '']]) self.assertEqual(str(new_s), str(s1))
def test_hint_can_reach_solution(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', '', 'B'], ['B', 'A', 'D', 'C'], ['D', 'C', 'B', 'A']]) for p in s.extensions(): print(p) self.assertEqual(hint_by_depth(s, 10), '(1, 2) -> A')
def test_nine_extensions(self): big = SudokuPuzzle([['E', 'C', '', '', 'G', '', '', '', ''], ['F', '', '', 'A', 'I', 'E', '', '', ''], ['', 'I', 'H', '', '', '', '', 'F', ''], ['H', '', '', '', 'F', '', '', '', 'C'], ['D', '', '', 'H', '', 'C', '', '', 'A'], ['G', '', '', '', 'B', '', '', '', 'F'], ['', 'F', '', '', '', '', 'B', 'H', ''], ['', '', '', 'D', 'A', 'I', '', '', 'E'], ['', '', '', '', 'H', '', '', 'G', 'I']]) self.assertEqual(big._possible_letters(4, 4), ['E']) self.assertEqual(big._possible_letters(3, 3), ['E', 'G', 'I'])
def test_dfs_solver_example() -> None: """Test DfsSolver.solve on a SudokuPuzzle.""" # This SudokuPuzzle is a more filled-in version of the one in the # example from the handout. s = SudokuPuzzle(4, [["C", "D", "B", "A"], ["B", "A", "D", "C"], ["D", " ", "A", " "], ["A", " ", "C", " "]], {"A", "B", "C", "D"}) solver = DfsSolver() actual = solver.solve(s)[-1] expected = SudokuPuzzle(4, [["C", "D", "B", "A"], ["B", "A", "D", "C"], ["D", "C", "A", "B"], ["A", "B", "C", "D"]], {"A", "B", "C", "D"}) assert actual == expected
def test_nine_extensions(self): big = SudokuPuzzle([ ['E', 'C', '', '', 'G', '', '', '', ''], ['F', '', '', 'A', 'I', 'E', '', '', ''], ['', 'I', 'H', '', '', '', '', 'F', ''], ['H', '', '', '', 'F', '', '', '', 'C'], ['D', '', '', 'H', '', 'C', '', '', 'A'], ['G', '', '', '', 'B', '', '', '', 'F'], ['', 'F', '', '', '', '', 'B', 'H', ''], ['', '', '', 'D', 'A', 'I', '', '', 'E'], ['', '', '', '', 'H', '', '', 'G', 'I']]) self.assertEqual(big._possible_letters(4, 4), ['E']) self.assertEqual(big._possible_letters(3, 3), ['E', 'G', 'I'])
def test_solve_complete(self): s = SudokuPuzzle([['A', 'B', '', ''], ['C', 'D', '', ''], ['B', '', '', ''], ['D', '', 'A', '']]) solutions = solve_complete(s) self.assertEqual(len(solutions), 2) for solution in solutions: self.assertTrue(solution.is_solved())
def check_relatives(self, cell, solver): if cell.current_value: if SudokuPuzzle.check_relatives(self, cell, solver): for killer_relation in self.killer_relations: if not killer_relation.check_relations(cell, solver): return False return True return False
def extensions(self) -> List[RandomizedSudokuPuzzle]: """ Return a list of extensions of this sudoku puzzle. The order of the extensions is randomized. """ exts = SudokuPuzzle.extensions(self) shuffle(exts) return exts
def load_puzzle(filename): """ utility method for loading a SudokuPuzzle from a csv file. zeros should be used to denote an 'unset' cell. """ puzzle = SudokuPuzzle() with open(filename, 'rb') as csvfile: reader = csv.reader(csvfile, delimiter=',') row_idx = 0 for row in reader: col_idx = 0 for col_str in row: col = int(col_str) if col > 0: puzzle.get_cell(row_idx, col_idx).fix_value(col) col_idx += 1 row_idx += 1 return puzzle
def test_solve_one(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', '', ''], ['D', 'C', '', '']]) solved = solve(s) # Note: when we run our tests, we will replace # this with our own "is_solved" method # to make sure the puzzle is correctly solved. # This means you should *not* change the internal state # of the Sudoku Puzzle class! self.assertTrue(solved.is_solved())
def main(): """Prompt the user to configure and play the game. @rtype: None """ game = input("Do you want to play Sudoku (s) or Word Ladder (w)? ") while game != "s" and game != "w": print("That is not a valid input.") game = input( "Do you want to play Sudoku (s) or Word Ladder (w)? ").lower() if game == "s": view_type = "text" g = SudokuPuzzle([['', '', '', 'A'], ['D', '', 'B', ''], ['C', '', '', ''], ['', 'B', '', 'D']]) print( "\n\nTo make a move: use the format (<row>, <column>) -> letter.") elif game == "w": view_type = input( "Would you like to play in text mode or web mode? ").lower() if view_type != "web" and view_type != "text": print( "That is not a valid mode, you will be playing in text mode.") view_type = "text" choice = input( "Do you want to choose your start and end words? (y/n) ") if choice == "y": print( "Your starting and ending words should have the same length.") start = input("What would you like your starting word to be? ") end = input("What would you like your ending word to be? ") while len(start) != len(end): print( "Your starting and ending words don't have the same length. Please try again." ) start = input("What would you like your starting word to be? ") end = input("What would you like your ending word to be? ") else: start = "rock" end = "taco" g = WordLadderPuzzle(start, end) print( "\n\nTo make a move, type a word which does not differ by more than one letter from the current word." ) if view_type == "text": print("To quit the game, type exit.") print("To ask for a solution, type :SOLVE.") print("To ask for a hint, type :HINT.") print("To undo a move, type :UNDO.") print( "To look at your past moves from this current game state, type :ATTEMPTS.\n" ) c = Controller(g, mode=view_type)
def test_sudoku_fail_fast_doctest() -> None: """Test SudokuPuzzle.fail_fast on the provided doctest.""" s = SudokuPuzzle(4, [["A", "B", "C", "D"], ["C", "D", " ", " "], [" ", " ", " ", " "], [" ", " ", " ", " "]], {"A", "B", "C", "D"}) assert s.fail_fast() is False s = SudokuPuzzle(4, [["B", "D", "A", "C"], ["C", "A", "B", "D"], ["A", "B", " ", " "], [" ", " ", " ", " "]], {"A", "B", "C", "D"}) assert s.fail_fast() is True
class KillerSudokuPuzzle(SudokuPuzzle): class KillerRelation: def __init__(self, total_value, cells): self.total_value = total_value self.relatives = cells #self.set_cage_member_values() def set_cage_member_values(self): available_values = cage_member_calculator.get_cage_members( len(self.relatives), self.total_value) for cell in self.relatives: cell.available_values = available_values def have_relation(self, cell): return cell in self.relatives def check_relations(self, cell, solver): if self.have_relation(cell): assigned_relatives = [ c for c in self.relatives if c.current_value != 0 ] if len(self.relatives) == len(assigned_relatives): if sum([v.current_value for v in self.relatives]) != self.total_value: return False else: return True if len(self.relatives) > len(assigned_relatives): if sum([v.current_value for v in self.relatives]) >= self.total_value: return False return True def __init__(self, initial_values): self.killer_relations = [] SudokuPuzzle.__init__(self, initial_values) self.verify_relatives() def parse_puzzle(self, (initial_values, killer_relations)): SudokuPuzzle.parse_puzzle(self, initial_values) for killer_relation in killer_relations: total_value, relatives = killer_relation self.killer_relations.append( KillerSudokuPuzzle.KillerRelation( total_value, [self.cells.get(c_id) for c_id in relatives]))
messages.append(outputs[i]) if i < len(commands): messages.append('Enter a command:\n> ') messages.append(commands[i] + '\n') if filename == '': print(''.join(messages)) else: with open(filename, 'w') as result_file: result_file.writelines(messages) if __name__ == '__main__': from sudoku_puzzle import SudokuPuzzle from word_ladder_puzzle import WordLadderPuzzle s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', '', ''], ['D', 'C', '', '']]) run_controller( s, [ '(2, 2) -> D', '(2, 3) -> D', # Note: invalid move ':UNDO', '(2, 3) -> C', ':UNDO', ':ATTEMPTS', ':UNDO', ':UNDO', ':ATTEMPTS', ':SOLVE' ],
def test_sample3(self): s = SudokuPuzzle([['A', 'B', '', 'D'], ['C', 'D', '', 'B'], ['B', '', '', ''], ['D', '', 'A', '']]) self.assertEqual(s._possible_letters(2, 3), ['C'])
def test_hint_no_possible_extensions(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', '', 'B'], ['B', 'A', 'D', 'C'], ['C', '', 'A', 'A']]) self.assertEqual(hint_by_depth(s, 10), 'No possible extensions!')
def __init__(self, initial_values): self.killer_relations = [] SudokuPuzzle.__init__(self, initial_values) self.verify_relatives()
def test_hint_already_solved(self): s = SudokuPuzzle([['A', 'B', 'C', 'D'], ['C', 'D', 'A', 'B'], ['B', 'A', 'D', 'C'], ['D', 'C', 'B', 'A']]) self.assertEqual(hint_by_depth(s, 10), 'Already at a solution!')
def test_hint_valid_state(self): s = SudokuPuzzle([['', 'B', 'C', 'D'], ['C', 'D', '', 'B'], ['B', '', 'D', 'C'], ['D', 'C', 'B', '']]) self.assertTrue( hint_by_depth(s, 3) in ['(0, 0) -> A', '(1, 2) -> A', '(2, 1) -> A', '(3, 3) -> A'])
hard_sudoku.append( '000570030100000020700023400000080004007004000490000605042000300000700900001800000' ) hard_sudoku.append( '700152300000000920000300000100004708000000060000000000009000506040907000800006010' ) hard_sudoku.append( '100007090030020008009600500005300900010080002600004000300000010040000007007000300' ) hard_sudoku.append( '100034080000800500004060021018000000300102006000000810520070900006009000090640002' ) hard_sudoku.append( '000920000006803000190070006230040100001000700008030029700080091000507200000064000' ) hard_sudoku.append( '060504030100090008000000000900050006040602070700040005000000000400080001050203040' ) hard_sudoku.append( '700000400020070080003008079900500300060020090001097006000300900030040060009001035' ) hard_sudoku.append( '000070020800000006010205000905400008000000000300008501000302080400000009070060000' ) for sudoku in easy_sudoku: SudokuSolver(SudokuPuzzle(sudoku)).solve() for sudoku in hard_sudoku: SudokuSolver(SudokuPuzzle(sudoku)).solve()
return [(puzzle.generate_hint(extension), True)] extension_hints = possible_hints(extension, n - 1) for hint in extension_hints: if hint[1]: # if this hint will lead to a solution return [(puzzle.generate_hint(extension), True)] # Else all the hints in extension do not lead to a solution # Only adds if lst is empty, since only one hint is necessary if len(lst) == 0 and len(extension_hints) > 0: lst.append((puzzle.generate_hint(extensions[0]), False)) return lst if __name__ == '__main__': from sudoku_puzzle import SudokuPuzzle from word_ladder_puzzle import WordLadderPuzzle s = SudokuPuzzle([['A', 'D', 'C', ''], ['B', 'C', '', ''], ['C', 'B', 'A', 'D'], ['D', 'A', 'B', 'C']]) print(s.extensions()[0]) print('The puzzle:') print(s) print('SOLVE') solve(s, True) print('\nSOLVE-ALL') solve_complete(s, True) print('\nHINT 1') print(hint_by_depth(s, 1))