Skip to content
Snippets Groups Projects
Commit 069f0bfe authored by Felix Agner's avatar Felix Agner
Browse files

optimized a bit

parent c2e7713a
No related branches found
No related tags found
No related merge requests found
...@@ -21,8 +21,7 @@ coord START; ...@@ -21,8 +21,7 @@ coord START;
coord END; coord END;
int N, M = 0; int N, M = 0;
array<array<bool, 145>, 145> IS_WALL = {true}; array<array<bool, 145>, 145> IS_WALL = {true};
map<coord, ll> TO_COME; vector <coord> FORWARD_PATH;
map<coord, ll> TO_GO;
void parse_input() { void parse_input() {
string line; string line;
...@@ -55,70 +54,60 @@ void parse_input() { ...@@ -55,70 +54,60 @@ void parse_input() {
} }
bool in_bounds(coord u) { bool in_bounds(coord u) {
return u.first >= 0 && u.first < M && u.second >= 0 && u.second < N; bool in = u.first >= 0 && u.first < M && u.second >= 0 && u.second < N;
return in && !IS_WALL[u.first][u.second];
} }
vector<coord> neighbors(coord u) { coord move(coord u, char d) {
vector<coord> n = { if (d == 'N') return {u.first - 1, u.second};
{u.first - 1, u.second}, if (d == 'S') return {u.first + 1, u.second};
{u.first + 1, u.second}, if (d == 'W') return {u.first, u.second - 1};
{u.first, u.second - 1}, if (d == 'E') return {u.first, u.second + 1};
{u.first, u.second + 1} return {-1, -1};
};
return n;
} }
vector<pair<coord,int>> cheat_neighbors(coord u, int cheat_length) { coord next(coord u, array<array<bool, 145>, 145> &visited) {
vector<pair<coord,int>> nlist; coord n = move(u, 'N');
if (in_bounds(n) && !visited[n.first][n.second]) return n;
// grab all squares within distance cheat_length that are not in a wall n = move(u, 'S');
for (int i = -cheat_length; i <= cheat_length; i++) { if (in_bounds(n) && !visited[n.first][n.second]) return n;
for (int j = -cheat_length + abs(i); j <= cheat_length - abs(i); j++) { n = move(u, 'W');
coord n = {u.first + i, u.second + j}; if (in_bounds(n) && !visited[n.first][n.second]) return n;
if (!in_bounds(n) || IS_WALL[n.first][n.second]) continue; n = move(u, 'E');
int cost = abs(i) + abs(j); if (in_bounds(n) && !visited[n.first][n.second]) return n;
return {-1, -1};
if (cost <= cheat_length) nlist.push_back({n, cost});
}
} }
return nlist; int dist(coord u, coord v) {
return abs(u.first - v.first) + abs(u.second - v.second);
} }
vector<coord> bfs(coord start) {
map<coord, ll> bfs(coord start) {
queue<tuple<ll, coord>> q;
q.push({0, start});
array<array<bool, 145>, 145> visited = {false}; array<array<bool, 145>, 145> visited = {false};
ll n_cheats = 0;
map<coord, ll> costs;
costs[start] = 0;
visited[start.first][start.second] = true; visited[start.first][start.second] = true;
vector<coord> path = {start};
coord curr = next(start, visited);
while (!q.empty()) { while (curr != END) {
auto [c, pos] = q.front(); q.pop(); visited[curr.first][curr.second] = true;
path.push_back(curr);
for (coord n : neighbors(pos)) if (in_bounds(n) && !IS_WALL[n.first][n.second] && !visited[n.first][n.second]) { curr = next(curr, visited);
q.push({c + 1, n});
costs[n] = c + 1;
visited[n.first][n.second] = true;
}
} }
path.push_back(END);
return costs; return path;
} }
ll n_cheats(int cheat_distance, ll baseline) { ll n_cheats(int cheat_distance, int improvement_goal) {
ll n_cheats = 0; ll n_cheats = 0;
for (auto [pos, cost] : TO_COME) if (cost < baseline) { for (int i = 0; i < FORWARD_PATH.size() - improvement_goal; i++) {
for (auto [cheat_pos, cheat_cost] : cheat_neighbors(pos, cheat_distance)) { for (int j = i + improvement_goal; j < FORWARD_PATH.size(); j++) {
if (TO_GO[cheat_pos] + cost + cheat_cost <= baseline) { int d = dist(FORWARD_PATH[i], FORWARD_PATH[j]);
n_cheats++; if (d > cheat_distance) j += max(d - cheat_distance-1, 0);
} else if (j - i - d >= improvement_goal) n_cheats++;
} }
} }
return n_cheats; return n_cheats;
...@@ -127,20 +116,19 @@ ll n_cheats(int cheat_distance, ll baseline) { ...@@ -127,20 +116,19 @@ ll n_cheats(int cheat_distance, ll baseline) {
int main (int argc, char* argv[]) { int main (int argc, char* argv[]) {
for (int i = 0; i < argc; i++) if (string(argv[i]) == "-d") DEBUG = true; for (int i = 0; i < argc; i++) if (string(argv[i]) == "-d") DEBUG = true;
if (DEBUG) cout << "Reading data..." << endl;
parse_input(); parse_input();
FORWARD_PATH = bfs(START);
TO_COME = bfs(START); if (DEBUG) cout << "Data read." << endl;
TO_GO = bfs(END);
ll baseline = TO_COME[END];
if (DEBUG) { if (DEBUG) {
cout << "Baseline: " << baseline << endl; cout << "Baseline: " << FORWARD_PATH.size() << endl;
} }
ll part1 = n_cheats(2, baseline - 100); ll part1 = n_cheats(2, 100);
cout << "Part 1: " << part1 << endl; cout << "Part 1: " << part1 << endl;
ll part2 = n_cheats(20, baseline - 100); ll part2 = n_cheats(20, 100);
cout << "Part 2: " << part2 << endl; cout << "Part 2: " << part2 << endl;
return 0; return 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment