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

I'm so sorry about this.

parent 361f688e
Branches
No related tags found
No related merge requests found
#include <bits/stdc++.h>
using namespace std;
const bool DEBUG = false;
#define coord pair <int, int>
#define ll long long
struct State {
coord pos;
char dir;
bool operator<(const State& other) const {
return tie(pos.first, pos.second, dir) < tie(other.pos.first, other.pos.second, other.dir);
}
};
map<char,coord> DIRMAP = {
{'N', {0, -1}},
{'S', {0, 1}},
{'W', {-1, 0}},
{'E', {1, 0}}
};
map<char,vector<char>> TURNMAP = {
{'N', {'W', 'E'}},
{'S', {'E', 'W'}},
{'W', {'S', 'N'}},
{'E', {'N', 'S'}}
};
coord GOAL;
vector<string> MAZE;
coord parse_input() {
string line;
coord start;
int row = 0;
while (getline(cin, line)) {
MAZE.push_back(line);
if (line.find('E') != string::npos) {
GOAL = {line.find('E'), row};
}
if (line.find('S') != string::npos) {
start = {line.find('S'), row};
}
row++;
}
return start;
}
void visualize(map<coord, bool> visited) {
vector<string> test_maze = MAZE;
for (auto v : visited) {
if (v.second) {
test_maze[v.first.second][v.first.first] = 'O';
}
}
for (auto row : test_maze) {
cout << row << endl;
}
}
vector<State> neighbor_states(State x0) {
vector<State> neighbors;
for (auto d : TURNMAP[x0.dir]) {
neighbors.push_back({x0.pos, d});
}
coord new_pos = {x0.pos.first + DIRMAP[x0.dir].first, x0.pos.second + DIRMAP[x0.dir].second};
neighbors.push_back({new_pos, x0.dir});
return neighbors;
}
pair<ll,ll> find_seats(coord start) {
State start_state = {start, 'E'};
map<State, ll> costs;
costs[start_state] = 0;
auto cost_comp = [&costs](const State& lhs, const State& rhs) {
return costs[lhs] > costs[rhs];
};
priority_queue<State, vector<State>, decltype(cost_comp)> q(cost_comp);
q.push(start_state);
ll cheapest_goal = LLONG_MAX;
set<char> goal_dirs = {};
map<State, vector<State>> path_to_goal;
while (!q.empty()) {
State cur = q.top();
q.pop();
if (MAZE[cur.pos.second][cur.pos.first] == '#') continue;
if (costs[cur] > cheapest_goal) break;
if (cur.pos == GOAL) {
if (goal_dirs.empty() || costs[cur] < cheapest_goal) {
goal_dirs = {cur.dir};
cheapest_goal = costs[cur];
} else if (costs[cur] == cheapest_goal) {
goal_dirs.insert(cur.dir);
}
}
for (auto n : neighbor_states(cur)) {
ll new_cost = costs[cur] + (n.dir == cur.dir ? 1 : 1000);
if (!costs.count(n) || costs[n] > new_cost) {
costs[n] = new_cost;
q.push(n);
path_to_goal[n] = {cur};
} else if (costs[n] == new_cost) {
path_to_goal[n].push_back(cur);
}
}
}
vector<State> part_of_path;
for (auto d : goal_dirs) {
part_of_path.push_back({GOAL, d});
}
map<coord, bool> visited;
ll count = 0;
while (!part_of_path.empty()) {
State cur = part_of_path.back();
part_of_path.pop_back();
if (!visited.count(cur.pos)) {
count++;
}
visited[cur.pos] = true;
for (auto p : path_to_goal[cur]) {
part_of_path.push_back(p);
}
}
if (DEBUG) visualize(visited);
return {cheapest_goal, count};
}
int main () {
coord start = parse_input();
if (DEBUG) {
cout << "Start " << start.first << " " << start.second << endl;
cout << "Goal " << GOAL.first << " " << GOAL.second << endl;
}
pair<ll,ll> parts = find_seats(start);
cout << "Part 1: " << parts.first << endl;
cout << "Part 2: " << parts.second << endl;
return 0;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment