diff options
Diffstat (limited to 'Source/Solver.cpp')
-rw-r--r-- | Source/Solver.cpp | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/Source/Solver.cpp b/Source/Solver.cpp new file mode 100644 index 0000000..244bfb2 --- /dev/null +++ b/Source/Solver.cpp | |||
@@ -0,0 +1,76 @@ | |||
1 | #include "Solver.h" | ||
2 | #include "Puzzle.h" | ||
3 | #include "Validator.h" | ||
4 | |||
5 | std::vector<Puzzle> Solver::Solve(Puzzle& p) { | ||
6 | std::vector<Puzzle> solutions; | ||
7 | // var start = (new Date()).getTime() | ||
8 | for (int x = 0; x < p.width; x++) { | ||
9 | for (int y = 0; y < p.height; y++) { | ||
10 | Cell cell = p.grid[x][y]; | ||
11 | if (cell.start) { | ||
12 | SolveLoop(p, x, y, solutions); | ||
13 | } | ||
14 | } | ||
15 | } | ||
16 | // var end = (new Date()).getTime() | ||
17 | // console.info('Solved', puzzle, 'in', (end-start)/1000, 'seconds') | ||
18 | return solutions; | ||
19 | } | ||
20 | |||
21 | void Solver::SolveLoop(Puzzle& p, int x, int y, std::vector<Puzzle>& solutions) { | ||
22 | // Stop trying to solve once we reach our goal | ||
23 | if (solutions.size() >= MAX_SOLUTIONS) return; | ||
24 | Cell cell = p.GetCell(x, y); | ||
25 | if (cell.undefined) return; | ||
26 | if (cell.gap != Cell::Gap::NONE) return; | ||
27 | |||
28 | if (p.sym == Puzzle::Symmetry::NONE) { | ||
29 | if (cell.color != Cell::Color::NONE) return; // Collided with ourselves | ||
30 | p.grid[x][y].color = Cell::Color::BLACK; // Otherwise, mark this cell as visited | ||
31 | } else { | ||
32 | /* | ||
33 | // Get the symmetrical position, and try coloring it | ||
34 | auto sym = p.GetSymmetricalPos(x, y); | ||
35 | Cell::Color oldColor = p.GetLine(sym.x, sym.y); | ||
36 | p.grid[sym.x][sym.y].color = Cell::Color::YELLOW; | ||
37 | |||
38 | // Collided with ourselves or our reflection | ||
39 | if (cell.color != Cell::Color::NONE) { | ||
40 | p.grid[sym.x, sym.y].color = oldColor; | ||
41 | return; | ||
42 | } | ||
43 | p.grid[x][y].color = Cell::Color::BLUE; // Otherwise, mark this cell as visited | ||
44 | */ | ||
45 | } | ||
46 | |||
47 | if (cell.end != Cell::Dir::NONE) { | ||
48 | // Reached an endpoint, validate solution and keep going -- there may be other endpoints | ||
49 | Validator::Validate(p); | ||
50 | if (p.valid) { | ||
51 | Puzzle clone = p; | ||
52 | solutions.push_back(clone); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | // Recursion order (LRUD) is optimized for BL->TR and mid-start puzzles | ||
57 | // Extend path left and right | ||
58 | if (y % 2 == 0) { | ||
59 | SolveLoop(p, x - 1, y, solutions); | ||
60 | SolveLoop(p, x + 1, y, solutions); | ||
61 | } | ||
62 | // Extend path up and down | ||
63 | if (x % 2 == 0) { | ||
64 | SolveLoop(p, x, y - 1, solutions); | ||
65 | SolveLoop(p, x, y + 1, solutions); | ||
66 | } | ||
67 | |||
68 | // Tail recursion: Back out of this cell | ||
69 | p.grid[x][y].color = Cell::Color::NONE; | ||
70 | if (p.sym != Puzzle::Symmetry::NONE) { | ||
71 | /* | ||
72 | auto sym = p.GetSymmetricalPos(x, y); | ||
73 | p.grid[sym.x][sym.y].color = Cell::Color::NONE; | ||
74 | */ | ||
75 | } | ||
76 | } | ||