Exemplo n.º 1
0
def _random_initial_cells(box_size: BoxSize) -> List[Cell]:
    size = box_size.width * box_size.length
    all_values = set(range(1, size + 1))

    values = random.sample(all_values, k=size)
    box_values = [
        values[i * box_size.length:i * box_size.length + box_size.length]
        for i in range(box_size.width)
    ]

    while True:  # pragma: no branch
        row_values = random.sample(all_values - set(box_values[0]),
                                   k=box_size.length)
        used_values = [sorted(box_values[i]) for i in range(1, box_size.width)]
        if sorted(row_values) not in used_values:
            break

    row_values += random.sample(all_values.difference(box_values[0],
                                                      row_values),
                                k=box_size.length)

    return [
        Cell(
            position=Position(row=i, column=j, box=box_size.sequential(i, j)),
            value=box_values[i][j],
        ) for i in range(box_size.width) for j in range(box_size.length)
    ] + [
        Cell(
            position=Position(row=0, column=i, box=box_size.sequential(0, i)),
            value=value,
        ) for i, value in enumerate(row_values, start=box_size.length)
    ]
Exemplo n.º 2
0
def test_locked_candidate_not_found():
    sudoku = make_sudoku_with_marks(
        [
            [2, 0, 0, 5, 9, 3, 1, 0, 0],
            [5, 0, 1, 0, 0, 2, 3, 0, 0],
            [3, 9, 7, 6, 4, 1, 8, 2, 5],
            [6, 0, 4, 0, 3, 8, 9, 0, 0],
            [8, 1, 0, 0, 0, 0, 0, 3, 6],
            [7, 3, 9, 0, 0, 6, 0, 0, 8],
            [1, 7, 0, 3, 0, 4, 6, 0, 0],
            [9, 0, 0, 0, 1, 5, 7, 4, 3],
            [4, 0, 3, 0, 6, 0, 0, 0, 1],
        ],
        box_size=BoxSize(3, 3),
    )

    sudoku.update([
        Cell(position=Position(1, 1, 0), candidates={4, 6}),
        Cell(position=Position(1, 7, 2), candidates={6, 9}),
        Cell(position=Position(1, 8, 2), candidates={4, 9}),
        Cell(position=Position(3, 3, 4), candidates={1, 2}),
        Cell(position=Position(8, 1, 6), candidates={2, 5, 8}),
        Cell(position=Position(8, 3, 7), candidates={7, 9}),
        Cell(position=Position(8, 5, 7), candidates={7, 9}),
        Cell(position=Position(8, 6, 8), candidates={2, 5}),
        Cell(position=Position(8, 7, 8), candidates={5, 8}),
    ])

    with pytest.raises(techniques.NotFound):
        techniques.LockedCandidate(sudoku).first()
Exemplo n.º 3
0
def test_locked_candidate_in_a_row():
    sudoku = make_sudoku_with_marks(
        [
            [9, 0, 0, 5, 3, 1, 2, 8, 0],
            [0, 2, 5, 7, 0, 4, 9, 3, 0],
            [0, 3, 0, 0, 0, 2, 0, 4, 0],
            [4, 8, 1, 2, 5, 7, 6, 9, 3],
            [3, 5, 9, 0, 0, 8, 0, 0, 2],
            [7, 6, 2, 3, 1, 9, 8, 5, 4],
            [0, 1, 0, 0, 0, 0, 0, 6, 8],
            [6, 0, 8, 1, 0, 5, 3, 0, 0],
            [0, 0, 3, 8, 7, 6, 0, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    locked_candidate = techniques.LockedCandidate(sudoku).first()

    assert locked_candidate.combination.cells == [
        Cell(position=Position(6, 3, 7), candidates={4, 9}),
        Cell(position=Position(6, 4, 7), candidates={2, 4, 9}),
    ]
    assert locked_candidate.combination.values == [9]

    assert locked_candidate.changes == [
        Cell(position=Position(7, 4, 7), candidates={2, 4})
    ]
Exemplo n.º 4
0
def test_locked_candidate_in_a_box():
    sudoku = make_sudoku_with_marks(
        [
            [2, 0, 0, 5, 9, 3, 1, 0, 0],
            [5, 0, 1, 0, 0, 2, 3, 0, 0],
            [3, 9, 7, 6, 4, 1, 8, 2, 5],
            [6, 0, 4, 0, 3, 8, 9, 0, 0],
            [8, 1, 0, 0, 0, 0, 0, 3, 6],
            [7, 3, 9, 0, 0, 6, 0, 0, 8],
            [1, 7, 0, 3, 0, 4, 6, 0, 0],
            [9, 0, 0, 0, 1, 5, 7, 4, 3],
            [4, 0, 3, 0, 6, 0, 0, 0, 1],
        ],
        box_size=BoxSize(3, 3),
    )

    sudoku.update([
        Cell(position=Position(1, 1, 0), candidates={4, 6}),
        Cell(position=Position(1, 7, 2), candidates={6, 9}),
        Cell(position=Position(1, 8, 2), candidates={4, 9}),
        Cell(position=Position(8, 3, 7), candidates={7, 9}),
        Cell(position=Position(8, 7, 8), candidates={5, 8}),
    ])

    locked_candidate = techniques.LockedCandidate(sudoku).first()

    assert locked_candidate.combination.cells == [
        Cell(position=Position(3, 7, 5), candidates={1, 5, 7}),
        Cell(position=Position(3, 8, 5), candidates={2, 7}),
    ]
    assert locked_candidate.combination.values == [7]

    assert locked_candidate.changes == [
        Cell(position=Position(3, 3, 4), candidates={1, 2})
    ]
Exemplo n.º 5
0
def test_naked_triplet():
    sudoku = make_sudoku_with_marks(
        [
            [9, 2, 6, 7, 3, 5, 4, 0, 0],
            [0, 0, 0, 6, 4, 9, 7, 2, 5],
            [7, 4, 5, 8, 2, 1, 9, 3, 6],
            [0, 1, 0, 0, 0, 8, 6, 4, 0],
            [5, 0, 4, 0, 0, 0, 8, 0, 0],
            [8, 6, 9, 1, 7, 4, 3, 5, 2],
            [0, 0, 0, 0, 8, 0, 0, 0, 0],
            [0, 0, 0, 9, 1, 0, 0, 6, 0],
            [0, 0, 0, 4, 0, 3, 1, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    naked_triplet = techniques.NakedTriplet(sudoku).first()

    assert naked_triplet.combination.cells == [
        Cell(position=Position(6, 7, 8), candidates={7, 9}),
        Cell(position=Position(8, 7, 8), candidates={7, 8, 9}),
        Cell(position=Position(8, 8, 8), candidates={7, 8, 9}),
    ]
    assert naked_triplet.combination.values == [7, 8, 9]

    by_position = operator.attrgetter("position")
    assert sorted(naked_triplet.changes, key=by_position) == [
        Cell(position=Position(6, 8, 8), candidates={3, 4}),
        Cell(position=Position(7, 8, 8), candidates={3, 4}),
    ]
Exemplo n.º 6
0
def test_naked_pair():
    sudoku = make_sudoku_with_marks(
        [
            [9, 2, 6, 7, 3, 5, 4, 0, 0],
            [0, 0, 0, 6, 4, 9, 7, 2, 5],
            [7, 4, 5, 8, 2, 1, 9, 3, 6],
            [0, 1, 0, 0, 0, 8, 6, 4, 0],
            [5, 0, 4, 0, 0, 0, 8, 0, 0],
            [8, 6, 9, 1, 7, 4, 3, 5, 2],
            [0, 0, 0, 0, 8, 0, 0, 0, 0],
            [0, 0, 0, 9, 1, 0, 0, 6, 0],
            [0, 0, 0, 4, 0, 3, 1, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )
    naked_pair = techniques.NakedPair(sudoku).first()

    assert naked_pair.combination.cells == [
        Cell(position=Position(6, 3, 7), candidates={2, 5}),
        Cell(position=Position(6, 6, 8), candidates={2, 5}),
    ]
    assert naked_pair.combination.values == [2, 5]

    by_position = operator.attrgetter("position")
    assert sorted(naked_pair.changes, key=by_position) == [
        Cell(position=Position(6, 0, 6), candidates={1, 3, 4, 6}),
        Cell(position=Position(6, 1, 6), candidates={3, 7, 9}),
        Cell(position=Position(6, 2, 6), candidates={1, 3, 7}),
        Cell(position=Position(6, 5, 7), candidates={6, 7}),
    ]
Exemplo n.º 7
0
def test_hidden_single():
    sudoku = make_sudoku_with_marks(
        [
            [9, 0, 6, 7, 0, 5, 0, 0, 0],
            [0, 0, 0, 0, 0, 9, 0, 2, 5],
            [7, 4, 0, 0, 0, 1, 0, 0, 0],
            [0, 1, 0, 0, 0, 0, 6, 4, 0],
            [5, 0, 0, 0, 0, 0, 0, 0, 0],
            [8, 6, 9, 1, 0, 0, 3, 0, 0],
            [0, 0, 0, 0, 8, 0, 0, 0, 0],
            [0, 0, 0, 9, 0, 0, 0, 6, 0],
            [0, 0, 0, 4, 0, 3, 1, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    hidden_single = techniques.HiddenSingle(sudoku).first()

    assert hidden_single.combination.cells == [
        Cell(position=Position(1, 6, 2), candidates={4, 7, 8})
    ]
    assert hidden_single.combination.values == [7]

    by_position = operator.attrgetter("position")
    assert sorted(hidden_single.changes, key=by_position) == [
        Cell(position=Position(1, 6, 2), value=7),
        Cell(position=Position(4, 6, 5), candidates={2, 8, 9}),
        Cell(position=Position(6, 6, 8), candidates={2, 4, 5, 9}),
        Cell(position=Position(7, 6, 8), candidates={2, 4, 5, 8}),
    ]
Exemplo n.º 8
0
def test_xy_wing():
    sudoku = make_sudoku_with_marks(
        [
            [2, 0, 0, 5, 9, 3, 1, 0, 0],
            [5, 0, 1, 0, 0, 2, 3, 0, 0],
            [3, 9, 7, 6, 4, 1, 8, 2, 5],
            [6, 0, 4, 0, 3, 8, 9, 0, 0],
            [8, 1, 0, 0, 0, 0, 0, 3, 6],
            [7, 3, 9, 0, 0, 6, 0, 0, 8],
            [1, 7, 0, 3, 0, 4, 6, 0, 0],
            [9, 0, 0, 0, 1, 5, 7, 4, 3],
            [4, 0, 3, 0, 6, 0, 0, 0, 1],
        ],
        box_size=BoxSize(3, 3),
    )

    sudoku.update([Cell(position=Position(3, 3, 4), candidates={1, 2})])

    xy_wing = techniques.XYWing(sudoku).first()

    assert xy_wing.combination.cells == [
        Cell(position=Position(3, 3, 4), candidates={1, 2}),
        Cell(position=Position(5, 4, 4), candidates={2, 5}),
        Cell(position=Position(5, 7, 5), candidates={1, 5}),
    ]
    assert xy_wing.combination.values == [1]
    assert xy_wing.changes == [
        Cell(position=Position(3, 7, 5), candidates={5, 7}),
        Cell(position=Position(5, 3, 4), candidates={2, 4}),
    ]
Exemplo n.º 9
0
def test_unique_rectangle_block_apart():
    sudoku = make_sudoku_with_marks(
        [
            [9, 0, 1, 0, 3, 0, 5, 0, 0],
            [0, 0, 7, 8, 1, 9, 0, 0, 0],
            [0, 2, 0, 4, 5, 6, 1, 9, 7],
            [1, 0, 2, 9, 0, 0, 6, 0, 5],
            [0, 0, 0, 6, 7, 1, 0, 2, 4],
            [6, 0, 0, 3, 2, 5, 8, 0, 0],
            [0, 1, 5, 0, 9, 0, 4, 6, 3],
            [0, 0, 6, 5, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, 6, 3, 0, 5, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    unique_rectangle = techniques.UniqueRectangle(sudoku).first()
    assert unique_rectangle.combination.cells == [
        Cell(position=Position(0, 3, 1), candidates={2, 7}),
        Cell(position=Position(0, 5, 1), candidates={2, 7}),
        Cell(position=Position(6, 3, 7), candidates={2, 7}),
        Cell(position=Position(6, 5, 7), candidates={2, 7, 8}),
    ]

    assert unique_rectangle.changes == [
        Cell(position=Position(6, 5, 7), candidates={8})
    ]
Exemplo n.º 10
0
def test_lone_single():
    sudoku = make_sudoku_with_marks(
        [
            [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),
    )
    lone_single = techniques.LoneSingle(sudoku).first()

    assert lone_single.combination.cells == [
        Cell(position=Position(1, 0, 0), candidates={5})
    ]
    assert lone_single.combination.values == [5]

    by_position = operator.attrgetter("position")
    assert sorted(lone_single.changes, key=by_position) == [
        Cell(position=Position(0, 0, 0), candidates={2, 3}),
        Cell(position=Position(0, 1, 0), candidates={2, 3, 4, 6, 8}),
        Cell(position=Position(0, 2, 0), candidates={2, 6, 8}),
        Cell(position=Position(1, 0, 0), value=5),
        Cell(position=Position(1, 1, 0), candidates={4, 6, 8, 9}),
        Cell(position=Position(1, 2, 0), candidates={1, 6, 8}),
        Cell(position=Position(1, 3, 1), candidates={4, 6, 7, 8}),
        Cell(position=Position(1, 4, 1), candidates={4, 7, 8}),
        Cell(position=Position(5, 0, 3), candidates={2, 3, 7}),
    ]
Exemplo n.º 11
0
def test_steps():
    given = 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),
    )

    assert [step.combination.name for step in solvers.steps(given)] == [
        "Bulk Pencil Marking",
        *["Lone Single"] * 8,
        *["Hidden Single"] * 7,
        "Lone Single",
        "Hidden Single",
        *["Naked Pair"] * 3,
        "Locked Candidate",
        "XY Wing",
        *["Hidden Single"] * 2,
        "Unique Rectangle",
        "Hidden Single",
        *["Lone Single"] * 2,
        "Hidden Single",
        *["Lone Single"] * 28,
    ]
Exemplo n.º 12
0
def test_backtrack():
    given = Sudoku.from_list(
        [
            [0, 0, 0, 8, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 4, 3],
            [5, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 7, 0, 8, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0],
            [0, 2, 0, 0, 3, 0, 0, 0, 0],
            [6, 0, 0, 0, 0, 0, 0, 7, 5],
            [0, 0, 3, 4, 0, 0, 0, 0, 0],
            [0, 0, 0, 2, 0, 0, 6, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )
    solution = solvers.backtrack(given)
    assert solution.is_solved() is True
    assert solution.is_valid() is True
    assert str(solution) == ("237841569"
                             "186795243"
                             "594326718"
                             "315674892"
                             "469582137"
                             "728139456"
                             "642918375"
                             "853467921"
                             "971253684")
Exemplo n.º 13
0
def test_eliminate():
    given = 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),
    )

    solution = solvers.eliminate(given)
    assert str(solution) == ("200593100"
                             "501002300"
                             "397641825"
                             "604038900"
                             "810000036"
                             "739006008"
                             "170304600"
                             "900015743"
                             "403060001")
Exemplo n.º 14
0
def test_unique_rectangle_not_found():
    sudoku = make_sudoku_with_marks(
        [
            [9, 2, 6, 7, 3, 5, 4, 0, 0],
            [0, 0, 0, 6, 4, 9, 7, 2, 5],
            [7, 4, 5, 8, 2, 1, 9, 3, 6],
            [0, 1, 0, 0, 0, 8, 6, 4, 0],
            [5, 0, 4, 0, 0, 0, 8, 0, 0],
            [8, 6, 9, 1, 7, 4, 3, 5, 2],
            [0, 0, 0, 0, 8, 0, 0, 0, 0],
            [0, 0, 0, 9, 1, 0, 0, 6, 0],
            [0, 0, 0, 4, 0, 3, 1, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    sudoku.update([
        Cell(position=Position(6, 0, 6), candidates={1, 6}),
        Cell(position=Position(6, 8, 8), candidates={3, 4}),
        Cell(position=Position(7, 0, 6), candidates={3, 4}),
        Cell(position=Position(7, 8, 8), candidates={3, 4}),
    ])

    with pytest.raises(techniques.NotFound):
        techniques.UniqueRectangle(sudoku).first()
Exemplo n.º 15
0
def test_unique_rectangle():
    sudoku = make_sudoku_with_marks(
        [
            [0, 6, 0, 8, 0, 2, 3, 7, 1],
            [3, 0, 7, 1, 6, 5, 8, 0, 4],
            [0, 8, 1, 3, 7, 0, 5, 6, 0],
            [8, 7, 4, 9, 2, 3, 1, 5, 6],
            [9, 1, 3, 6, 5, 8, 2, 4, 7],
            [6, 0, 0, 4, 1, 7, 9, 3, 8],
            [0, 3, 8, 0, 0, 0, 6, 1, 5],
            [0, 0, 6, 0, 8, 1, 4, 0, 3],
            [1, 4, 0, 5, 3, 6, 7, 8, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    assert len(list(techniques.UniqueRectangle(sudoku))) == 1

    unique_rectangle = techniques.UniqueRectangle(sudoku).first()
    assert unique_rectangle.combination.cells == [
        Cell(position=Position(6, 0, 6), candidates={2, 7}),
        Cell(position=Position(6, 3, 7), candidates={2, 7}),
        Cell(position=Position(7, 0, 6), candidates={2, 5, 7}),
        Cell(position=Position(7, 3, 7), candidates={2, 7}),
    ]
    assert unique_rectangle.combination.values == [2, 7]
    assert unique_rectangle.changes == [
        Cell(position=Position(7, 0, 6), candidates={5}),
    ]
Exemplo n.º 16
0
 def get_object(self):
     queryset = self.filter_queryset(self.get_queryset())
     instance = queryset.random()
     if not instance:
         raise exceptions.NotFound
     return SudokuGrid.from_string(
         instance.puzzle, box_size=BoxSize(instance.box_width, instance.box_length),
     )
Exemplo n.º 17
0
def test_random_initial_cells():
    box_size = BoxSize(3, 3)
    cells = generators._random_initial_cells(box_size)
    assert len(cells) == 15

    sudoku = Sudoku(*cells, box_size=box_size)
    assert sudoku.is_valid() is True
    assert sudoku.is_solved() is False
Exemplo n.º 18
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
Exemplo n.º 19
0
def test_sudoku():
    sudoku = Sudoku(
        Cell(position=Position(0, 0, 0), value=2),
        Cell(position=Position(0, 1, 0), candidates=set()),
        box_size=BoxSize(3, 3),
    )
    assert sudoku[0, 0].value == 2
    assert sudoku[0, 1].candidates == set()
    assert sudoku[0, 2].value is None
    assert len(sudoku[0, 2].candidates) == 0
Exemplo n.º 20
0
 def create(self, validated_data):
     return Sudoku(
         *[
             Cell(
                 position=Position(*cell["position"]),
                 value=cell["value"],
                 candidates=set(cell["candidates"]),
             ) for cell in validated_data["cells"]
         ],
         box_size=BoxSize(*validated_data["box_size"]),
     )
Exemplo n.º 21
0
def test_rank_sudoku_with_multiple_solutions():
    puzzle = [
        [8, 1, 0, 0, 0, 0, 6, 7, 9],
        [0, 0, 0, 6, 7, 9, 0, 2, 0],
        [0, 0, 0, 1, 2, 8, 3, 0, 0],
        [0, 3, 4, 0, 5, 7, 0, 0, 0],
        [2, 0, 0, 0, 0, 0, 7, 0, 4],
        [0, 0, 0, 0, 0, 6, 0, 0, 0],
        [0, 0, 3, 7, 0, 1, 0, 6, 2],
        [0, 0, 0, 0, 0, 0, 4, 0, 0],
        [0, 0, 1, 0, 3, 0, 0, 8, 0],
    ]
    sudoku = Sudoku.from_list(puzzle, box_size=BoxSize(3, 3))
    with pytest.raises(exceptions.MultipleSolutions):
        stats.rank(sudoku)
Exemplo n.º 22
0
def sudoku():
    return Sudoku.from_list(
        [
            [0, 0, 7, 0, 3, 0, 8, 0, 0],
            [0, 0, 0, 2, 0, 5, 0, 0, 0],
            [4, 0, 0, 9, 0, 6, 0, 0, 1],
            [0, 4, 3, 0, 0, 0, 2, 1, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 5],
            [0, 5, 8, 0, 0, 0, 6, 7, 0],
            [5, 0, 0, 1, 0, 8, 0, 0, 9],
            [0, 0, 0, 5, 0, 3, 0, 0, 0],
            [0, 0, 2, 0, 9, 0, 5, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )
Exemplo n.º 23
0
def test_from_string(sudoku_12x12):
    sudoku = Sudoku.from_string(
        "300974B1068C"
        "800692C0B430"
        "00040365020A"
        "C561BA000923"
        "284A6073C0B5"
        "7B93C0504006"
        "A4072B309000"
        "0900000CA060"
        "031C08A9270B"
        "4000A0276019"
        "92A030100070"
        "060B0C000052",
        box_size=BoxSize(3, 4),
    )
    assert list(sudoku.cells()) == list(sudoku_12x12.cells())
Exemplo n.º 24
0
def test_hidden_single_not_found():
    sudoku = make_sudoku_with_marks(
        [
            [9, 2, 6, 7, 3, 5, 4, 0, 0],
            [0, 0, 0, 6, 4, 9, 7, 2, 5],
            [7, 4, 5, 8, 2, 1, 9, 3, 6],
            [0, 1, 0, 0, 0, 8, 6, 4, 0],
            [5, 0, 4, 0, 0, 0, 8, 0, 0],
            [8, 6, 9, 1, 7, 4, 3, 5, 2],
            [0, 0, 0, 0, 8, 0, 0, 0, 0],
            [0, 0, 0, 9, 1, 0, 0, 6, 0],
            [0, 0, 0, 4, 0, 3, 1, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )
    with pytest.raises(techniques.NotFound):
        techniques.HiddenSingle(sudoku).first()
Exemplo n.º 25
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)
Exemplo n.º 26
0
def test_xy_wing_not_found():
    sudoku = make_sudoku_with_marks(
        [
            [2, 0, 0, 5, 9, 3, 1, 0, 0],
            [5, 0, 1, 0, 0, 2, 3, 0, 0],
            [3, 9, 7, 6, 4, 1, 8, 2, 5],
            [6, 0, 4, 0, 3, 8, 9, 0, 0],
            [8, 1, 0, 0, 0, 0, 0, 3, 6],
            [7, 3, 9, 0, 0, 6, 0, 0, 8],
            [1, 7, 0, 3, 0, 4, 6, 0, 0],
            [9, 0, 0, 0, 1, 5, 7, 4, 3],
            [4, 0, 3, 0, 6, 0, 0, 0, 1],
        ],
        box_size=BoxSize(3, 3),
    )

    with pytest.raises(techniques.NotFound):
        techniques.XYWing(sudoku).first()
Exemplo n.º 27
0
def test_steps_raises_unsolvable():
    given = Sudoku.from_list(
        [
            [7, 0, 0, 0, 8, 2, 5, 0, 0],
            [0, 5, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 9, 0, 7, 0, 2, 6],
            [0, 0, 8, 0, 9, 0, 0, 7, 5],
            [3, 0, 0, 6, 7, 5, 0, 0, 0],
            [0, 0, 0, 0, 2, 0, 0, 9, 0],
            [9, 0, 1, 0, 0, 3, 0, 0, 0],
            [0, 0, 0, 0, 6, 0, 0, 0, 3],
            [6, 0, 2, 0, 0, 0, 0, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    with pytest.raises(exceptions.Unsolvable):
        list(solvers.steps(given))
Exemplo n.º 28
0
def test_lone_single_not_found():
    sudoku = make_sudoku_with_marks(
        [
            [9, 0, 6, 7, 0, 5, 0, 0, 0],
            [0, 0, 0, 0, 0, 9, 0, 2, 5],
            [7, 4, 0, 0, 0, 1, 0, 0, 0],
            [0, 1, 0, 0, 0, 0, 6, 4, 0],
            [5, 0, 0, 0, 0, 0, 0, 0, 0],
            [8, 6, 9, 1, 0, 0, 3, 0, 0],
            [0, 0, 0, 0, 8, 0, 0, 0, 0],
            [0, 0, 0, 9, 0, 0, 0, 6, 0],
            [0, 0, 0, 4, 0, 3, 1, 0, 0],
        ],
        box_size=BoxSize(3, 3),
    )

    with pytest.raises(techniques.NotFound):
        techniques.LoneSingle(sudoku).first()
Exemplo n.º 29
0
def sudoku_12x12():
    return Sudoku.from_list(
        [
            [3, 0, 0, 9, 7, 4, 11, 1, 0, 6, 8, 12],
            [8, 0, 0, 6, 9, 2, 12, 0, 11, 4, 3, 0],
            [0, 0, 0, 4, 0, 3, 6, 5, 0, 2, 0, 10],
            [12, 5, 6, 1, 11, 10, 0, 0, 0, 9, 2, 3],
            [2, 8, 4, 10, 6, 0, 7, 3, 12, 0, 11, 5],
            [7, 11, 9, 3, 12, 0, 5, 0, 4, 0, 0, 6],
            [10, 4, 0, 7, 2, 11, 3, 0, 9, 0, 0, 0],
            [0, 9, 0, 0, 0, 0, 0, 12, 10, 0, 6, 0],
            [0, 3, 1, 12, 0, 8, 10, 9, 2, 7, 0, 11],
            [4, 0, 0, 0, 10, 0, 2, 7, 6, 0, 1, 9],
            [9, 2, 10, 0, 3, 0, 1, 0, 0, 0, 7, 0],
            [0, 6, 0, 11, 0, 12, 0, 0, 0, 0, 5, 2],
        ],
        box_size=BoxSize(3, 4),
    )
Exemplo n.º 30
0
def random_sudoku(avg_rank: int = 150,
                  box_size: BoxSize = BoxSize(3, 3)) -> Sudoku:
    sudoku = Sudoku(*_random_initial_cells(box_size), box_size=box_size)
    solution = solvers.backtrack(sudoku)

    iterations = min(avg_rank, MAX_ITERATIONS)
    for i in range(iterations):
        size = random.randint(1, 2)
        rows = [random.randint(0, solution.size - 1) for _ in range(size)]
        columns = [random.randint(0, solution.size - 1) for _ in range(size)]
        cells = [solution[row, column] for (row, column) in zip(rows, columns)]
        if all(cell.value for cell in cells):
            solution.update([Cell(position=cell.position) for cell in cells])
            try:
                stats.rank(solution)
            except exceptions.MultipleSolutions:
                solution.update(cells)

    return solution