150 lines
4.4 KiB
C++
150 lines
4.4 KiB
C++
#include <vector>
|
|
#include <algorithm>
|
|
#include <ranges>
|
|
#include <numeric>
|
|
#include <cmath>
|
|
#include <utility>
|
|
|
|
#include "aoc.hpp"
|
|
#include "aoc/utils.hpp"
|
|
#include "fmt/format.h"
|
|
|
|
using namespace std::string_view_literals;
|
|
using namespace aoc::types;
|
|
|
|
namespace lab {
|
|
|
|
class guard {
|
|
public:
|
|
guard(i64 x, i64 y) : m_row(y), m_col(x) { }
|
|
|
|
auto set_direction(i64 x, i64 y) -> void {
|
|
m_dx = x;
|
|
m_dy = y;
|
|
}
|
|
auto set_dx(i64 x) -> void { m_dx = x; }
|
|
auto set_dy(i64 y) -> void { m_dy = y; }
|
|
auto set_x(i64 v) -> void { m_col = v; }
|
|
auto set_y(i64 v) -> void { m_row = v; }
|
|
auto x() const -> i64 { return m_col; }
|
|
auto y() const -> i64 { return m_row; }
|
|
auto dx() const -> i64 { return m_dx; }
|
|
auto dy() const -> i64 { return m_dy; }
|
|
|
|
auto move() -> void {
|
|
m_row += m_dy;
|
|
m_col += m_dx;
|
|
}
|
|
|
|
private:
|
|
i64 m_row;
|
|
i64 m_col;
|
|
i64 m_dx;
|
|
i64 m_dy;
|
|
};
|
|
|
|
class lab {
|
|
public:
|
|
lab(std::string const& map_str) {
|
|
auto const lines = map_str
|
|
| std::views::split("\n"sv)
|
|
| std::views::transform([](auto const& str) {
|
|
return std::string_view(std::begin(str), std::end(str));
|
|
})
|
|
| std::views::filter([](auto const& str) { return !str.empty(); })
|
|
| std::views::transform([](auto const& str) {
|
|
return str | std::views::filter([](auto const& ch) { return ch != '\n'; })
|
|
| std::ranges::to<std::vector>();
|
|
}) | std::ranges::to<std::vector>();
|
|
|
|
m_rows = lines.size();
|
|
m_cols = lines[0].size();
|
|
std::ranges::for_each(lines, [&](auto const& str) {
|
|
std::ranges::for_each(str, [&](auto const& ch) {
|
|
m_data.emplace_back(ch);
|
|
});
|
|
});
|
|
|
|
auto it = std::find_if(std::begin(m_data), std::end(m_data), [](auto const ch) { return ch == '^'; });
|
|
if (it != std::end(m_data)) m_start.set_direction(0, -1);
|
|
|
|
auto const dist = usize(it - std::begin(m_data));
|
|
m_start.set_x(i64(dist - (dist / m_cols * m_rows)));
|
|
m_start.set_y(i64(dist / m_cols));
|
|
}
|
|
|
|
auto start() const -> guard { return m_start; }
|
|
auto rows() const -> usize { return m_rows; }
|
|
auto cols() const -> usize { return m_cols; }
|
|
|
|
auto is_obstruction(usize x, usize y) const -> bool {
|
|
if (x >= m_cols || y >= m_rows) return false;
|
|
return m_data[y * m_cols + x] == '#';
|
|
}
|
|
|
|
auto is_obstruction(guard const& g) const -> bool {
|
|
return is_obstruction(usize(g.x()), usize(g.y()));
|
|
}
|
|
|
|
auto is_outside(usize x, usize y) const -> bool {
|
|
return x >= m_cols || y >= m_rows;
|
|
}
|
|
|
|
auto is_outside(guard const& g) const -> bool {
|
|
return is_outside(usize(g.x()), usize(g.y()));
|
|
}
|
|
|
|
private:
|
|
usize m_rows{};
|
|
usize m_cols{};
|
|
std::vector<u8> m_data{};
|
|
guard m_start{0, 0};
|
|
};
|
|
}
|
|
|
|
auto part_a(lab::lab const& map) -> void {
|
|
// for (usize i = 0; i < map.rows; ++i) {
|
|
// for (usize j = 0; j < map.cols; ++j) {
|
|
// fmt::print("{} ", c8(map.data[i * map.cols + j]));
|
|
// }
|
|
// fmt::print("\n");
|
|
// }
|
|
std::vector<u8> cpy{};
|
|
cpy.resize(map.rows() * map.cols());
|
|
std::fill(std::begin(cpy), std::end(cpy), 0);
|
|
|
|
auto guard = map.start();
|
|
|
|
while (!map.is_outside(guard)) {
|
|
cpy[usize(guard.y()) * map.cols() + usize(guard.x())] = 1;
|
|
lab::guard guard_cpy = guard;
|
|
guard_cpy.move();
|
|
|
|
if (map.is_obstruction(guard_cpy)) {
|
|
if (guard_cpy.dy() == -1)
|
|
guard.set_direction(1, 0);
|
|
else if (guard_cpy.dy() == 1)
|
|
guard.set_direction(-1, 0);
|
|
else if (guard_cpy.dx() == -1)
|
|
guard.set_direction(0, -1);
|
|
else if (guard_cpy.dx() == 1)
|
|
guard.set_direction(0, 1);
|
|
}
|
|
guard.move();
|
|
}
|
|
|
|
auto const sum = std::accumulate(std::begin(cpy), std::end(cpy), 0);
|
|
fmt::print("Part A: {}\n", sum);
|
|
}
|
|
|
|
auto aoc24::day06([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
|
auto res = aoc::read_text("./dat/24/re/06.txt");
|
|
if (!res) return std::unexpected(res.error());
|
|
auto const map_txt = *res;
|
|
|
|
lab::lab map{map_txt};
|
|
part_a(map);
|
|
|
|
return {};
|
|
}
|