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