-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolver.cpp
139 lines (119 loc) · 5.17 KB
/
solver.cpp
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
#include "solver.h"
#include <iostream>
#include <set>
#include <ctime>
using std::set;
using std::pair;
Solver::Solver() {
solution = vector<pair<int, int>>();
}
Solver::Solver(Grid& g) {
grid = g;
solution = vector<pair<int, int>>();
}
void Solver::set(Grid& g) {
grid = g;
solution.clear();
}
void Solver::path(pair<int, int> src, pair<int, int> prev) { // Currently this only works if the start point is on the edge or a border (due to the pruning system).
callstopath++;
// cout << "[" << src.first << " " << src.second << "]\n";
if (solution.size() > 0) return;
if ((grid.ends).find(src) != (grid.ends).end()) {
grid.board[src.first][src.second]->isPathOccupied = true;
// cout << "ENDPOINT " << src.first << " " << src.second << endl;
// grid.disp();
bool check = grid.ver(origin.first, origin.second);
// cout << (check ? "PASSED\n" : "FAILED\n");
if (check) {
// cout << "SOLUTION FOUND" << endl;
vis.insert({src, prev});
// for (auto i : vis) cout << "[" << i.first.first << " " << i.first.second << "] [" << i.second.first << " " << i.second.second << "]\n";
while (vis.find(src) != vis.end() && vis.at(src) != src) {
// cout << src.first << " " << src.second << endl;
solution.push_back(src);
src = vis.at(src);
}
solution.push_back(src);
reverse(solution.begin(), solution.end());
}
grid.board[src.first][src.second]->isPathOccupied = false;
return;
}
// Basic pruning action
// This can be toggled by changing the loop constraints.
for (int ii = 0; ii < 4; ii++) {
pair<int, int> x0 = {src.first + dx[(ii + 0) % 4], src.second + dy[(ii + 0) % 4]};
pair<int, int> x1 = {src.first + dx[(ii + 1) % 4], src.second + dy[(ii + 1) % 4]};
// pair<int, int> x2 = {src.first + dx[(ii + 2) % 4], src.second + dy[(ii + 2) % 4]};
pair<int, int> x3 = {src.first + dx[(ii + 3) % 4], src.second + dy[(ii + 3) % 4]};
bool blocked0 = !grid.inside(x0);
bool blocked1 = !grid.inside(x1) || grid.board[x1.first][x1.second]->isPathOccupied;
// bool blocked2 = !grid.inside(x2);
bool blocked3 = !grid.inside(x3) || grid.board[x3.first][x3.second]->isPathOccupied;
vector<pair<int, int>> banned({src, x0});
if (blocked0 && !blocked1 && !blocked3) {
// cout << "BLOCKED!!! " << src.first << " " << src.second << endl;
// grid.disp();
bool r1 = grid.validateRegion(x1.first, x1.second, banned);
bool r3 = grid.validateRegion(x3.first, x3.second, banned);
if (!r1 && !r3) {
// cout << "INVALID" << endl;
return;
}
break;
}
}
vis.insert({src, prev});
grid.board[src.first][src.second]->isPathOccupied = true;
srand(time(0));
int offset = rand() % 4;
for (int ii = 0; ii < 4; ii++) {
int i = (ii + offset) % 4;
pair<int, int> next = {src.first + dx[i], src.second + dy[i]};
if (!grid.inside(next)) continue;
if (!grid.board[next.first][next.second]->isPath) continue;
if (vis.find(next) != vis.end()) continue;
path(next, src);
}
vis.erase(vis.find(src));
grid.board[src.first][src.second]->isPathOccupied = false;
}
vector<pair<int, int>> Solver::solve() {
// cout << "SOLVING" << endl;
callstopath = 0;
solution.clear();
for (auto i : grid.starts) {
origin = i;
// cout << i.first << " " << i.second << endl;
vis.clear();
vis.insert({i, i});
path(i, i);
if (solution.size() > 0) break;
}
return solution;
}
string Solver::to_string() {
for (auto i : grid.board) {
for (auto j : i) j->isPathOccupied = false;
}
for (auto i : solution) grid.board[i.first][i.second]->isPathOccupied = true;
string res = grid.to_string();
for (auto i : solution) grid.board[i.first][i.second]->isPathOccupied = false;
return res;
}
void Solver::disp() {
cout << to_string() << endl;
cout << callstopath << " CALLS TO PATH\n\n";
}
void Solver::activate() {
for (auto i : grid.board) {
for (auto j : i) j->isPathOccupied = false;
}
for (auto i : solution) grid.board[i.first][i.second]->isPathOccupied = true;
}
void Solver::deactivate() {
for (auto i : grid.board) {
for (auto j : i) j->isPathOccupied = false;
}
}