Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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)
Example #6
0
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
Example #7
0
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
Example #8
0
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