-
Notifications
You must be signed in to change notification settings - Fork 0
/
BoxLineReductionStrategy.cs
145 lines (137 loc) · 4.9 KB
/
BoxLineReductionStrategy.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Linq;
using System.Collections.Generic;
using SudokuBrain.Services;
public class BoxLineReductionStrategy : IStrategy
{
private readonly IMessageLogger _logger;
public BoxLineReductionStrategy(IMessageLogger logger)
{
_logger = logger;
}
public string Name => "Box line reduction";
public int SkillLevel => 4;
// For each row and column, check if all instances of a candidate are in the same box
public bool Apply(Puzzle puzzle)
{
bool progress = false;
_puzzle = puzzle;
for (int num = 1; num <= 9; num++)
{
var line = puzzle.GetColumn(num);
progress = ApplyToLine(line, num, true) || progress;
line = puzzle.GetRow(num);
progress = ApplyToLine(line, num, false) || progress;
}
return progress;
}
private Puzzle _puzzle;
public bool ApplyToLine(Group line, int lineNum, bool isColumn)
{
bool progress = false;
foreach (var candidate in line.Candidates)
{
// Check if this digit is a candidate in only 2 or 3 locations
var cellNumbers = new HashSet<int>();
for (int cellNum = 1; cellNum <= 9; cellNum++)
{
var cell = line.GetCell(cellNum);
if (!cell.Filled && cell.Candidates.Contains(candidate))
{
cellNumbers.Add(cellNum);
}
}
if (cellNumbers.Count == 2 || cellNumbers.Count == 3)
{
// Check if our candidates are all in the same box number
int boxNum = 0;
bool valid = true;
foreach (var cellNum in cellNumbers)
{
int currentBoxNum;
if (isColumn)
{
currentBoxNum = Helpers.BoxNumber(lineNum, cellNum);
}
else
{
currentBoxNum = Helpers.BoxNumber(cellNum, lineNum);
}
if (boxNum == 0)
{
// First cell - record the box number
boxNum = currentBoxNum;
}
else if (boxNum != currentBoxNum)
{
// Subsequent cell was not in the same box number
valid = false;
break;
}
}
if (valid)
{
// Remove this candidate from all the other cells in the box
IList<int> skipCells;
if (isColumn)
{
if (lineNum % 3 == 1)
{
skipCells = Constants.BoxLeftCol;
}
else if (lineNum % 3 == 2)
{
skipCells = Constants.BoxMiddleCol;
}
else
{
skipCells = Constants.BoxRightCol;
}
}
else
{
if (lineNum % 3 == 1)
{
skipCells = Constants.BoxTopRow;
}
else if (lineNum % 3 == 2)
{
skipCells = Constants.BoxMiddleRow;
}
else
{
skipCells = Constants.BoxBottomRow;
}
}
var box = _puzzle.GetBox(boxNum);
bool boxProgress = false;
for (int b = 1; b <= 9; b++)
{
if (!skipCells.Contains(b))
{
// This cell isnt in our column/row - remove the candidate
var boxCell = box.GetCell(b);
if (boxCell.EliminateCandidate(candidate, Name))
{
boxProgress = true;
}
}
}
if (boxProgress)
{
progress = true;
if (isColumn)
{
_logger.Log(Name, $"{candidate}s all in a column in box {boxNum}");
}
else
{
_logger.Log(Name, $"{candidate}s all in a row in box {boxNum}");
}
}
}
}
}
return progress;
}
}