def steps(sudoku: Sudoku) -> Iterator[Step]: _sudoku = Sudoku(*sudoku.cells(), box_size=sudoku.box_size) all_techniques: Tuple[Type[Technique], ...] = ( techniques.LoneSingle, techniques.HiddenSingle, techniques.NakedPair, techniques.NakedTriplet, techniques.LockedCandidate, techniques.XYWing, techniques.UniqueRectangle, ) for step in techniques.BulkPencilMarking(_sudoku): _sudoku.update(step.changes) yield step while not _sudoku.is_solved(): for technique in all_techniques: try: step = technique(_sudoku).first() except techniques.NotFound: continue else: _sudoku.update(step.changes) yield step break else: raise exceptions.Unsolvable
def test_plain(): expected = ( "┌─────────┬─────────┬─────────╥─────────┬─────────┬─────────╥─────────┬─────────┬─────────┐\n" # noqa: E501 "│ 2 3 │ 2 3 │ 2 ║ 3 │ │ 3 ║ │ │ │\n" # noqa: E501 "│ 5 │ 4 5 6 │ 5 6 ║ 4 5 6 │ 9 │ 4 5 6 ║ 1 │ 6 │ 4 6 │\n" # noqa: E501 "│ │ 8 │ 8 ║ 7 8 │ │ 7 ║ │ 7 │ 7 │\n" # noqa: E501 "├─────────┼─────────┼─────────╫─────────┼─────────┼─────────╫─────────┼─────────┼─────────┤\n" # noqa: E501 "│ │ │ 1 ║ │ │ ║ │ │ │\n" # noqa: E501 "│ 5 │ 4 5 6 │ 5 6 ║ 4 5 6 │ 4 5 │ 2 ║ 3 │ 6 │ 4 6 │\n" # noqa: E501 "│ │ 8 9 │ 8 ║ 7 8 │ 7 8 │ ║ │ 7 9 │ 7 9 │\n" # noqa: E501 "├─────────┼─────────┼─────────╫─────────┼─────────┼─────────╫─────────┼─────────┼─────────┤\n" # noqa: E501 "│ 3 │ 3 │ ║ 3 │ │ ║ │ │ │\n" # noqa: E501 "│ │ 4 6 │ 7 ║ 4 6 │ 4 │ 1 ║ 8 │ 2 │ 5 │\n" # noqa: E501 "│ │ 9 │ ║ │ │ ║ │ │ │\n" # noqa: E501 "╞═════════╪═════════╪═════════╬═════════╪═════════╪═════════╬═════════╪═════════╪═════════╡\n" # noqa: E501 "│ │ 2 │ ║ 1 2 │ │ ║ │ 1 │ 2 │\n" # noqa: E501 "│ 6 │ 5 │ 4 ║ 5 │ 3 │ 8 ║ 9 │ 5 │ │\n" # noqa: E501 "│ │ │ ║ 7 │ │ ║ │ 7 │ 7 │\n" # noqa: E501 "├─────────┼─────────┼─────────╫─────────┼─────────┼─────────╫─────────┼─────────┼─────────┤\n" # noqa: E501 "│ │ │ 2 ║ 2 │ 2 │ ║ 2 │ 3 │ 2 │\n" # noqa: E501 "│ 8 │ 1 │ 5 ║ 4 5 6 │ 4 5 │ 4 5 6 ║ 4 5 │ 5 6 │ 4 6 │\n" # noqa: E501 "│ │ │ ║ 7 9 │ 7 │ 7 9 ║ │ 7 │ 7 │\n" # noqa: E501 "├─────────┼─────────┼─────────╫─────────┼─────────┼─────────╫─────────┼─────────┼─────────┤\n" # noqa: E501 "│ 2 3 │ 2 3 │ ║ 1 2 │ 2 │ ║ 2 │ 1 3 │ │\n" # noqa: E501 "│ 5 │ 5 │ 9 ║ 4 5 6 │ 4 5 │ 4 5 6 ║ 4 5 │ 5 6 │ 8 │\n" # noqa: E501 "│ 7 │ │ ║ 7 │ 7 │ 7 ║ │ 7 │ │\n" # noqa: E501 "╞═════════╪═════════╪═════════╬═════════╪═════════╪═════════╬═════════╪═════════╪═════════╡\n" # noqa: E501 "│ │ │ 2 ║ 2 3 │ 2 │ 3 ║ │ │ 2 │\n" # noqa: E501 "│ 1 │ 7 │ 5 ║ 4 5 │ 4 5 │ 4 5 ║ 6 │ 5 │ │\n" # noqa: E501 "│ │ │ 8 ║ 8 9 │ 8 │ 9 ║ │ 8 9 │ 9 │\n" # noqa: E501 "├─────────┼─────────┼─────────╫─────────┼─────────┼─────────╫─────────┼─────────┼─────────┤\n" # noqa: E501 "│ │ 2 │ 2 ║ 2 │ │ ║ │ │ │\n" # noqa: E501 "│ 9 │ 5 6 │ 5 6 ║ 5 │ 1 │ 5 ║ 7 │ 4 │ 3 │\n" # noqa: E501 "│ │ 8 │ 8 ║ 8 │ │ ║ │ │ │\n" # noqa: E501 "├─────────┼─────────┼─────────╫─────────┼─────────┼─────────╫─────────┼─────────┼─────────┤\n" # noqa: E501 "│ │ 2 │ ║ 2 │ │ ║ 2 │ │ │\n" # noqa: E501 "│ 4 │ 5 │ 3 ║ 5 │ 6 │ 5 ║ 5 │ 5 │ 1 │\n" # noqa: E501 "│ │ 8 │ ║ 7 8 9 │ │ 7 9 ║ │ 8 9 │ │\n" # noqa: E501 "└─────────┴─────────┴─────────╨─────────┴─────────┴─────────╨─────────┴─────────┴─────────┘" # noqa: E501 ) sudoku = Sudoku.from_list( [ [0, 0, 0, 0, 9, 0, 1, 0, 0], [0, 0, 0, 0, 0, 2, 3, 0, 0], [0, 0, 7, 0, 0, 1, 8, 2, 5], [6, 0, 4, 0, 3, 8, 9, 0, 0], [8, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 9, 0, 0, 0, 0, 0, 8], [1, 7, 0, 0, 0, 0, 6, 0, 0], [9, 0, 0, 0, 1, 0, 7, 4, 3], [4, 0, 3, 0, 6, 0, 0, 0, 1], ], box_size=BoxSize(3, 3), ) sudoku.update(techniques.BulkPencilMarking(sudoku).first().changes) assert renderers.plain(sudoku) == expected
def test_bulk_pencil_marking(): sudoku = Sudoku.from_list( [ [0, 0, 0, 0, 9, 0, 1, 0, 0], [0, 0, 0, 0, 0, 2, 3, 0, 0], [0, 0, 7, 0, 0, 1, 8, 2, 5], [6, 0, 4, 0, 3, 8, 9, 0, 0], [8, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 9, 0, 0, 0, 0, 0, 8], [1, 7, 0, 0, 0, 0, 6, 0, 0], [9, 0, 0, 0, 1, 0, 7, 4, 3], [4, 0, 3, 0, 6, 0, 0, 0, 1], ], box_size=BoxSize(3, 3), ) pencil_marks = techniques.BulkPencilMarking(sudoku).first() assert len(pencil_marks.changes) == 51 assert len(list(techniques.BulkPencilMarking(sudoku))) == 1
def test_returns_hint_for_sudoku_with_pencil_marks(rf): sudoku = generators.random_sudoku(avg_rank=1) sudoku.update(techniques.BulkPencilMarking(sudoku).first().changes) url = reverse("hint") serializer = serializers.SudokuSerializer(sudoku) request = rf.post(url, data=serializer.data, content_type="application/json") response = views.Hints.as_view()(request) content = json.loads(response.rendered_content) assert content["combination"]["name"] == "Lone Single" assert response.status_code == 200
def test_colorful(): sudoku = Sudoku.from_list( [ [0, 0, 0, 0, 9, 0, 1, 0, 0], [0, 0, 0, 0, 0, 2, 3, 0, 0], [0, 0, 7, 0, 0, 1, 8, 2, 5], [6, 0, 4, 0, 3, 8, 9, 0, 0], [8, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 9, 0, 0, 0, 0, 0, 8], [1, 7, 0, 0, 0, 0, 6, 0, 0], [9, 0, 0, 0, 1, 0, 7, 4, 3], [4, 0, 3, 0, 6, 0, 0, 0, 1], ], box_size=BoxSize(3, 3), ) sudoku.update(techniques.BulkPencilMarking(sudoku).first().changes) assert "\033[93m2\033[0m" in renderers.colorful(sudoku)
def test_hint_for_invalid_sudoku(rf): sudoku = generators.random_sudoku(avg_rank=1) sudoku.update(techniques.BulkPencilMarking(sudoku).first().changes) sudoku.update( [ Cell(position=Position(0, 0, 0), value=1), Cell(position=Position(0, 1, 0), value=1), ] ) url = reverse("hint") serializer = serializers.SudokuSerializer(sudoku) request = rf.post(url, data=serializer.data, content_type="application/json") response = views.Hints.as_view()(request) content = json.loads(response.rendered_content) assert content["code"] == "invalid_puzzle" assert response.status_code == 400
def eliminate(sudoku: Sudoku) -> Sudoku: _sudoku = Sudoku(*sudoku.cells(), box_size=sudoku.box_size) all_techniques = ( techniques.LoneSingle, techniques.HiddenSingle, ) for step in techniques.BulkPencilMarking(_sudoku): _sudoku.update(step.changes) has_result = True while has_result: for technique in all_techniques: has_result = False for step in technique(_sudoku): _sudoku.update(step.changes) has_result = True return _sudoku
def make_sudoku_with_marks(puzzle: List[List[int]], box_size: BoxSize) -> Sudoku: sudoku = Sudoku.from_list(puzzle, box_size=box_size) sudoku.update(techniques.BulkPencilMarking(sudoku).first().changes) return sudoku