225 lines
4.6 KiB
C++
225 lines
4.6 KiB
C++
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <vector>
|
||
|
#include <map>
|
||
|
#include <set>
|
||
|
using namespace std;
|
||
|
|
||
|
void parseGrid(const char *path, vector<vector<char>> &grid) {
|
||
|
ifstream input(path);
|
||
|
|
||
|
string line;
|
||
|
while (getline(input, line)) {
|
||
|
stringstream line_stream;
|
||
|
line_stream << line;
|
||
|
vector<char> line_vec;
|
||
|
|
||
|
char c;
|
||
|
while (line_stream >> c) {
|
||
|
line_vec.push_back(c);
|
||
|
}
|
||
|
|
||
|
grid.push_back(line_vec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void printGrid(vector<vector<char>> grid) {
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[0].size(); x++) {
|
||
|
cout << grid[y][x] << " ";
|
||
|
}
|
||
|
cout << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// do one move and save new position in x and y
|
||
|
// returns false if the guard left the grid.
|
||
|
bool move(vector<vector<char>> &grid, int &x_ret, int &y_ret, char &c) {
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[y].size(); x++) {
|
||
|
if (grid[y][x] == 'v') {
|
||
|
// cout << "down" << endl;
|
||
|
if (y == grid.size() - 1) {
|
||
|
grid[y][x] = '.';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
c = 'v';
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (grid[y + 1][x] == '#') {
|
||
|
grid[y][x] = '<';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
c = 'v';
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
grid[y][x] = '.';
|
||
|
grid[y + 1][x] = 'v';
|
||
|
c = 'v';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
} else if (grid[y][x] == '^') {
|
||
|
// cout << "up" << endl;
|
||
|
if (y == 0) {
|
||
|
grid[y][x] = '.';
|
||
|
c = '^';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (grid[y - 1][x] == '#') {
|
||
|
grid[y][x] = '>';
|
||
|
c = '^';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
grid[y][x] = '.';
|
||
|
grid[y - 1][x] = '^';
|
||
|
c = '^';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
} else if (grid[y][x] == '>') {
|
||
|
// cout << "right" << endl;
|
||
|
if (x == grid[y].size() - 1) {
|
||
|
grid[y][x] = '.';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
c = '>';
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (grid[y][x + 1] == '#') {
|
||
|
grid[y][x] = 'v';
|
||
|
c = '>';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
grid[y][x] = '.';
|
||
|
grid[y][x + 1] = '>';
|
||
|
c = '>';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
} else if (grid[y][x] == '<') {
|
||
|
// cout << "left" << endl;
|
||
|
if (x == 0) {
|
||
|
grid[y][x] = '.';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
c = '<';
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (grid[y][x - 1] == '#') {
|
||
|
grid[y][x] = '^';
|
||
|
c = '<';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
grid[y][x] = '.';
|
||
|
grid[y][x - 1] = '<';
|
||
|
c = '<';
|
||
|
x_ret = x;
|
||
|
y_ret = y;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void part1(const char *path) {
|
||
|
vector<vector<char>> grid;
|
||
|
int x;
|
||
|
int y;
|
||
|
char c;
|
||
|
|
||
|
parseGrid(path, grid);
|
||
|
|
||
|
set<char, greater<char>> visited[grid.size()][grid[0].size()];
|
||
|
// initialize vector
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[0].size(); x++) {
|
||
|
set<char, greater<char>> s;
|
||
|
visited[y][x] = s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int sum = 0;
|
||
|
while (move(grid, x, y, c)) {
|
||
|
if (!visited[y][x].size()) {
|
||
|
sum++;
|
||
|
visited[y][x].insert(c);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cout << path << "1: " << sum << endl;
|
||
|
}
|
||
|
|
||
|
bool has_loop(vector<vector<char>> grid) {
|
||
|
// printGrid(grid);
|
||
|
int x;
|
||
|
int y;
|
||
|
char c;
|
||
|
set<char, greater<char>> visited[grid.size()][grid[0].size()];
|
||
|
// initialize vector
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[0].size(); x++) {
|
||
|
set<char, greater<char>> s;
|
||
|
visited[y][x] = s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (move(grid, x, y, c)) {
|
||
|
// cout << endl;
|
||
|
// printGrid(grid);
|
||
|
if (visited[y][x].count(c)) {
|
||
|
return true;
|
||
|
}
|
||
|
visited[y][x].insert(c);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void part2(const char *path) {
|
||
|
vector<vector<char>> grid;
|
||
|
parseGrid(path, grid);
|
||
|
|
||
|
int sum = 0;
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[0].size(); x++) {
|
||
|
// cout << "x= " << x << " y= " << y << endl;
|
||
|
if (grid[y][x] == '.') {
|
||
|
grid[y][x] = '#';
|
||
|
// cout << "before has_loop" << endl;
|
||
|
if (has_loop(grid)) sum++;
|
||
|
// cout << "after has_loop" << sum << endl;
|
||
|
grid[y][x] = '.';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
cout << path << "2: " << sum << endl;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
part1("example");
|
||
|
part1("input");
|
||
|
part2("example");
|
||
|
part2("input");
|
||
|
|
||
|
return 0;
|
||
|
}
|