#include #include #include #include #include #include #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::ranges::to(); 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 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 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 const& args) -> std::expected { 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 {}; }