+day06 part2
This commit is contained in:
parent
5309f9bb14
commit
f74a1558f1
1 changed files with 130 additions and 0 deletions
130
2024/day06/part2.cc
Normal file
130
2024/day06/part2.cc
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
|
||||
class vec {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
vec(int x, int y) : x(x), y(y) {}
|
||||
vec operator+(const vec& other) const;
|
||||
int index(int width) const;
|
||||
vec right() const;
|
||||
auto operator<=>(const vec&) const = default;
|
||||
};
|
||||
|
||||
vec vec::operator+(const vec& other) const {
|
||||
return vec{x + other.x, y + other.y};
|
||||
}
|
||||
|
||||
int vec::index(int width) const {
|
||||
return y * width + x;
|
||||
}
|
||||
|
||||
vec vec::right() const {
|
||||
return vec{-y, x};
|
||||
}
|
||||
|
||||
class grid {
|
||||
int width;
|
||||
int height;
|
||||
std::vector<bool> obstacles;
|
||||
std::vector<bool> visited_pos;
|
||||
std::set<std::pair<vec, vec>> visited;
|
||||
public:
|
||||
grid(int width, int height);
|
||||
bool visit(const vec& v, const vec& dir);
|
||||
void obstacle(const vec& v);
|
||||
bool is_obstacle(const vec& v) const;
|
||||
bool is_valid(const vec& v) const;
|
||||
bool is_visited(const vec& v) const;
|
||||
};
|
||||
|
||||
grid::grid(int width, int height)
|
||||
: width(width), height(height) {
|
||||
obstacles.resize(width * height);
|
||||
visited_pos.resize(width * height);
|
||||
}
|
||||
|
||||
bool grid::visit(const vec& v, const vec& dir) {
|
||||
visited_pos[v.index(width)] = true;
|
||||
return visited.emplace(v, dir).second;
|
||||
}
|
||||
|
||||
void grid::obstacle(const vec& v) {
|
||||
obstacles[v.index(width)] = true;
|
||||
}
|
||||
|
||||
bool grid::is_obstacle(const vec& v) const {
|
||||
return obstacles.at(v.index(width));
|
||||
}
|
||||
|
||||
bool grid::is_valid(const vec& v) const {
|
||||
return v.x >= 0 && v.x < width
|
||||
&& v.y >= 0 && v.y < height;
|
||||
}
|
||||
|
||||
bool grid::is_visited(const vec& v) const {
|
||||
return visited_pos.at(v.index(width));
|
||||
}
|
||||
|
||||
bool is_loop(grid& g, vec pos, vec dir) {
|
||||
for (;; pos = pos + dir) {
|
||||
if (!g.is_valid(pos + dir)) {
|
||||
return false;
|
||||
}
|
||||
while (g.is_obstacle(pos + dir)) {
|
||||
dir = dir.right();
|
||||
}
|
||||
if (!g.visit(pos, dir)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int width = 0, height = 0, count = 0;
|
||||
std::string line;
|
||||
std::vector<vec> obstacles;
|
||||
std::set<vec> counted;
|
||||
vec pos{0, 0};
|
||||
vec dir{0, -1};
|
||||
for (int line_num = 0; getline(std::cin, line); line_num++) {
|
||||
height++;
|
||||
for (int x = 0; x < line.size(); x++) {
|
||||
if (line[x] == '#') {
|
||||
obstacles.emplace_back(x, line_num);
|
||||
} else if (line[x] == '^') {
|
||||
pos = vec{x, line_num};
|
||||
}
|
||||
}
|
||||
}
|
||||
width = line.size();
|
||||
grid g{width, height};
|
||||
for (const vec& v : obstacles) {
|
||||
g.obstacle(v);
|
||||
}
|
||||
grid tmp{width, height};
|
||||
for (;; pos = pos + dir) {
|
||||
if (!g.is_valid(pos + dir)) {
|
||||
break;
|
||||
}
|
||||
while (g.is_obstacle(pos + dir)) {
|
||||
dir = dir.right();
|
||||
}
|
||||
if (!g.is_visited(pos + dir)) {
|
||||
tmp = g;
|
||||
tmp.obstacle(pos + dir);
|
||||
if (is_loop(tmp, pos, dir)) {
|
||||
if (counted.emplace(pos + dir).second) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
g.visit(pos, dir);
|
||||
}
|
||||
std::cout << count << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Add table
Reference in a new issue