+day06 part2

This commit is contained in:
Naomi Amethyst 2024-12-21 06:22:38 +00:00
parent 5309f9bb14
commit f74a1558f1
Signed by: naomi
GPG key ID: 89CA5D5A1F99F982

130
2024/day06/part2.cc Normal file
View 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;
}