44 apply_box_line_claiming ,
55 apply_hidden_pair ,
66 apply_hidden_triple ,
7+ apply_hidden_single ,
78 apply_locked_candidates_pointing ,
9+ apply_naked_single ,
810 apply_naked_pair ,
911 apply_naked_triple ,
1012 apply_x_wing ,
@@ -27,6 +29,98 @@ def _set_candidates(cand: list[list[set[int]]], r: int, c: int, values: set[int]
2729 cand [r ][c ].update (values )
2830
2931
32+ def test_naked_single_places_value () -> None :
33+ grid = _empty_grid ()
34+ for c , value in enumerate (range (1 , 9 )):
35+ grid [0 ][c ] = value
36+ cand = candidates (grid )
37+
38+ move = apply_naked_single (grid , cand )
39+
40+ assert move is not None
41+ assert move ["strategy" ] == "naked_single"
42+ assert move ["type" ] == "place"
43+ assert move ["r" ] == 0 and move ["c" ] == 8
44+ assert move ["v" ] == 9
45+ assert grid [0 ][8 ] == 9
46+
47+
48+ def test_hidden_single_row_metadata () -> None :
49+ grid = _empty_grid ()
50+ cand = candidates (grid )
51+ digit = 7
52+ _clear_digit (cand , digit )
53+ cand [2 ][4 ].update ({digit , 9 })
54+
55+ move = apply_hidden_single (grid , cand )
56+
57+ assert move is not None
58+ assert move ["strategy" ] == "hidden_single"
59+ assert move ["unit" ] == "row"
60+ assert move ["unit_index" ] == 2
61+ assert move ["r" ] == 2 and move ["c" ] == 4
62+ assert move ["v" ] == digit
63+ assert grid [2 ][4 ] == digit
64+
65+
66+ def test_hidden_single_column_metadata () -> None :
67+ grid = _empty_grid ()
68+ cand = candidates (grid )
69+ digit = 5
70+ _clear_digit (cand , digit )
71+ cand [1 ][3 ].update ({digit , 9 })
72+ cand [1 ][5 ].add (digit )
73+
74+ move = apply_hidden_single (grid , cand )
75+
76+ assert move is not None
77+ assert move ["strategy" ] == "hidden_single"
78+ assert move ["unit" ] == "col"
79+ assert move ["unit_index" ] == 3
80+ assert move ["r" ] == 1 and move ["c" ] == 3
81+ assert move ["v" ] == digit
82+ assert grid [1 ][3 ] == digit
83+
84+
85+ def test_hidden_single_box_metadata () -> None :
86+ grid = _empty_grid ()
87+ cand = candidates (grid )
88+ digit = 6
89+ _clear_digit (cand , digit )
90+ for r , c in (
91+ (7 , 7 ),
92+ (7 , 0 ),
93+ (4 , 7 ),
94+ (4 , 6 ),
95+ (1 , 6 ),
96+ (1 , 2 ),
97+ (5 , 2 ),
98+ (5 , 5 ),
99+ (0 , 5 ),
100+ (0 , 3 ),
101+ (6 , 3 ),
102+ (6 , 4 ),
103+ (3 , 4 ),
104+ (3 , 0 ),
105+ (2 , 0 ),
106+ (2 , 1 ),
107+ (1 , 1 ),
108+ (2 , 7 ),
109+ (6 , 1 ),
110+ ):
111+ cand [r ][c ].add (digit )
112+
113+ move = apply_hidden_single (grid , cand )
114+
115+ assert move is not None
116+ assert move ["strategy" ] == "hidden_single"
117+ assert move ["unit" ] == "box"
118+ assert move ["unit_index" ] == 8
119+ assert move ["r" ] == 7 and move ["c" ] == 7
120+ assert move ["v" ] == digit
121+ assert grid [7 ][7 ] == digit
122+
123+
30124def test_locked_candidates_pointing_row () -> None :
31125 grid = _empty_grid ()
32126 cand = candidates (grid )
0 commit comments