Skip to content

Commit 2a2c905

Browse files
Add step_once priority tests
1 parent ca1564a commit 2a2c905

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

tests/test_strategies_core.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
from __future__ import annotations
22

3+
from unittest.mock import patch
4+
35
from sudoku_dlx.strategies import (
46
apply_box_line_claiming,
57
apply_hidden_pair,
8+
apply_hidden_single,
69
apply_hidden_triple,
710
apply_locked_candidates_pointing,
811
apply_naked_pair,
912
apply_naked_triple,
1013
apply_x_wing,
1114
candidates,
15+
step_once,
1216
)
1317

1418

@@ -226,3 +230,79 @@ def test_x_wing_rows_then_cols() -> None:
226230
assert move_col["strategy"] == "x_wing_col"
227231
assert move_col["digit"] == digit_col
228232
assert digit_col not in cand2[3][0]
233+
234+
235+
def test_step_once_prefers_naked_single_over_hidden_single() -> None:
236+
grid = _empty_grid()
237+
cand = candidates(grid)
238+
239+
_set_candidates(cand, 0, 0, {1})
240+
_set_candidates(cand, 0, 1, {2, 3})
241+
for c in range(9):
242+
if c != 1:
243+
cand[0][c].discard(2)
244+
245+
grid_hidden = [row[:] for row in grid]
246+
cand_hidden = [[cell.copy() for cell in row] for row in cand]
247+
hidden_move = apply_hidden_single(grid_hidden, cand_hidden)
248+
249+
assert hidden_move is not None
250+
assert hidden_move["strategy"] == "hidden_single"
251+
252+
with patch("sudoku_dlx.strategies.candidates", return_value=cand):
253+
move = step_once(grid)
254+
255+
assert move is not None
256+
assert move["strategy"] == "naked_single"
257+
assert move["r"] == 0 and move["c"] == 0
258+
assert grid[0][0] == 1
259+
260+
261+
def test_step_once_prioritizes_locked_pointing_before_box_line() -> None:
262+
grid = _empty_grid()
263+
cand = candidates(grid)
264+
265+
for r in range(3):
266+
for c in range(3):
267+
cand[r][c].discard(1)
268+
_set_candidates(cand, 0, 0, {1, 2})
269+
_set_candidates(cand, 0, 1, {1, 3})
270+
_set_candidates(cand, 0, 5, {1, 4, 5})
271+
272+
for c in range(9):
273+
if c not in (3, 4):
274+
cand[1][c].discard(4)
275+
_set_candidates(cand, 1, 3, {4, 5})
276+
_set_candidates(cand, 1, 4, {4, 6})
277+
_set_candidates(cand, 0, 3, {2, 4, 7})
278+
279+
grid_locked = [row[:] for row in grid]
280+
cand_locked = [[cell.copy() for cell in row] for row in cand]
281+
locked_move = apply_locked_candidates_pointing(grid_locked, cand_locked)
282+
283+
assert locked_move is not None
284+
assert locked_move["strategy"].startswith("locked_pointing")
285+
286+
grid_box_line = [row[:] for row in grid]
287+
cand_box_line = [[cell.copy() for cell in row] for row in cand]
288+
box_line_move = apply_box_line_claiming(grid_box_line, cand_box_line)
289+
290+
assert box_line_move is not None
291+
assert box_line_move["strategy"].startswith("box_line")
292+
293+
with patch("sudoku_dlx.strategies.candidates", return_value=cand):
294+
move = step_once(grid)
295+
296+
assert move is not None
297+
assert move["strategy"].startswith("locked_pointing")
298+
assert grid == _empty_grid()
299+
300+
301+
def test_step_once_returns_none_when_no_moves_available() -> None:
302+
grid = _empty_grid()
303+
snapshot = [row[:] for row in grid]
304+
305+
move = step_once(grid)
306+
307+
assert move is None
308+
assert grid == snapshot

0 commit comments

Comments
 (0)