+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