2 * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
7 #include "SudokuSolver.h"
9 #include "SudokuField.h"
15 SolutionStep(const SudokuField
* field
);
16 SolutionStep(const SolutionStep
& other
);
22 void SetSolvedFields();
24 SudokuField
* Field() { return fField
; }
25 uint32
X() { return fX
; }
26 uint32
Y() { return fY
; }
34 typedef std::vector
<SolutionStep
*> StepList
;
38 bit_count(uint32 value
)
53 SolutionStep::SolutionStep(const SudokuField
* _field
)
55 fField
= new SudokuField(*_field
);
61 SolutionStep::SolutionStep(const SolutionStep
& other
)
63 fField
= new SudokuField(*other
.fField
);
69 SolutionStep::~SolutionStep()
76 SolutionStep::ToFirstUnset()
78 for (uint32 y
= 0; y
< fField
->Size(); y
++) {
79 for (uint32 x
= 0; x
< fField
->Size(); x
++) {
80 if (!fField
->ValueAt(x
, y
)) {
81 uint32 validMask
= fField
->ValidMaskAt(x
, y
);
82 if (bit_count(validMask
) == 1) {
83 // If the chosen value is already solved, we set its
84 // value here and go on - this makes sure the first
85 // unset we return has actually more than one possible
88 while ((validMask
& (1UL << value
)) == 0) {
91 fField
->SetValueAt(x
, y
, value
+ 1, true);
106 SolutionStep::ToNextUnset()
108 for (uint32 y
= fY
; y
< fField
->Size(); y
++) {
109 for (uint32 x
= 0; x
< fField
->Size(); x
++) {
110 if (y
== fY
&& x
== 0) {
115 if (!fField
->ValueAt(x
, y
)) {
130 SudokuSolver::SudokuSolver(SudokuField
* field
)
137 SudokuSolver::SudokuSolver()
144 SudokuSolver::~SudokuSolver()
146 // we don't own the field but the solutions
152 SudokuSolver::_MakeEmpty()
154 for (uint32 i
= 0; i
< fSolutions
.size(); i
++) {
155 delete fSolutions
[i
];
161 SudokuSolver::SetTo(SudokuField
* field
)
168 SudokuSolver::ComputeSolutions()
172 // We need to check if generating a solution is affordable with a
173 // brute force algorithm like this one
175 for (uint32 y
= 0; y
< fField
->Size(); y
++) {
176 for (uint32 x
= 0; x
< fField
->Size(); x
++) {
177 if (fField
->ValueAt(x
, y
))
181 if (set
< fField
->Size() * fField
->Size() / 6)
184 Stack
<SolutionStep
*> stack
;
185 SolutionStep
* step
= new SolutionStep(fField
);
186 step
->ToFirstUnset();
191 // brute force version
193 while (stack
.Pop(&step
)) {
194 uint32 x
= step
->X();
195 uint32 y
= step
->Y();
196 uint32 validMask
= step
->Field()->ValidMaskAt(x
, y
);
200 if (step
->ToNextUnset()) {
201 if (validMask
!= 0) {
202 // generate further steps
203 for (uint32 i
= 0; i
< fField
->Size(); i
++) {
204 if ((validMask
& (1UL << i
)) == 0)
207 SolutionStep
* next
= new SolutionStep(*step
);
208 next
->Field()->SetValueAt(x
, y
, i
+ 1, true);
212 } else if (step
->Field()->IsSolved())
213 fSolutions
.push_back(new SudokuField(*step
->Field()));
218 //printf("evaluated %lu steps\n", count);
223 SudokuSolver::CountSolutions()
225 return fSolutions
.size();
230 SudokuSolver::SolutionAt(uint32 index
)
232 return fSolutions
[index
];