#include #include #include #include #include #include #include #include "aoc.hpp" #include "aoc/utils.hpp" #include "fmt/format.h" #include "ctre.hpp" namespace cms { using vecn = std::vector; using matnxn = std::vector; auto read_text_matnxn(std::string const& path) -> matnxn { std::ifstream strm{path}; if (!strm.is_open()) throw std::runtime_error(fmt::format("Failed to open file {}", path)); matnxn text{}; vecn cols{}; while (!strm.eof()) { auto const c = static_cast(strm.peek()); if (c == '\n') text.emplace_back(std::move(cols)); else cols.push_back(c); strm.get(); } return text; } } auto part_a(cms::matnxn const& mat) -> void { std::vector pattern{'X', 'M', 'A', 'S'}; aoc::i32 hc = 0; aoc::i32 vc = 0; aoc::i32 xc = 0; for (std::size_t i = 0; i < mat.size(); ++i) { auto const& cols = mat[i]; auto hview = cols | std::views::slide(4) | std::views::filter([&](auto const& str) { auto const a = std::ranges::all_of( std::views::zip(pattern, str), [](auto const& z) { return std::get<0>(z) == std::get<1>(z); }); auto const b = std::ranges::all_of( std::views::zip(std::views::reverse(pattern), str), [](auto const& z) { return std::get<0>(z) == std::get<1>(z); }); return a || b; }); hc += std::ranges::distance(hview); for (std::size_t j = 0; j < cols.size(); ++j) { // Vertical pattern bool is_v_match = true; bool is_rv_match = true; for (std::size_t y = 0; y < pattern.size(); ++y) { if (i + y >= mat.size()) { is_v_match = false; is_rv_match = false; break; } if (is_v_match) is_v_match = mat[i + y][j] == pattern[y]; if (is_rv_match) is_rv_match = mat[i + y][j] == pattern[pattern.size() - y - 1]; } vc += is_v_match ? 1 : 0; vc += is_rv_match ? 1 : 0; bool is_dr_match = true; bool is_drr_match = true; for (std::size_t x = 0; x < pattern.size(); ++x) { if (i + x >= mat.size() || j + x >= cols.size()) { is_dr_match = false; is_drr_match = false; break; } if (is_dr_match) is_dr_match = mat[i + x][j + x] == pattern[x]; if (is_drr_match) is_drr_match = mat[i + x][j + x] == pattern[pattern.size() - x - 1]; } xc += is_dr_match ? 1 : 0; xc += is_drr_match ? 1 : 0; bool is_dl_match = true; bool is_dlr_match = true; for (std::size_t x = 0; x < pattern.size(); ++x) { if (i + x >= mat.size() || j + pattern.size() - 1 >= cols.size()) { is_dl_match = false; is_dlr_match = false; break; } if (is_dl_match) is_dl_match = mat[i + x][j + pattern.size() - x - 1] == pattern[x]; if (is_dlr_match) is_dlr_match = mat[i + x][j + pattern.size() - x - 1] == pattern[pattern.size() - x - 1]; } xc += is_dl_match ? 1 : 0; xc += is_dlr_match ? 1 : 0; } } // fmt::print("{}\n", hc); // fmt::print("{}\n", vc); // fmt::print("{}\n", xc); fmt::print("Part A: {}\n", hc + vc + xc); } auto part_b(cms::matnxn const& mat) -> void { std::vector pattern{'M', 'A', 'S'}; aoc::i32 xc = 0; for (std::size_t i = 0; i < mat.size(); ++i) { auto const& cols = mat[i]; for (std::size_t j = 0; j < cols.size(); ++j) { bool is_dr_match = true; bool is_drr_match = true; for (std::size_t x = 0; x < pattern.size(); ++x) { if (i + x >= mat.size() || j + x >= cols.size()) { is_dr_match = false; is_drr_match = false; break; } if (is_dr_match) is_dr_match = mat[i + x][j + x] == pattern[x]; if (is_drr_match) is_drr_match = mat[i + x][j + x] == pattern[pattern.size() - x - 1]; } bool is_dl_match = true; bool is_dlr_match = true; for (std::size_t x = 0; x < pattern.size(); ++x) { if (i + x >= mat.size() || j + pattern.size() - 1 >= cols.size()) { is_dl_match = false; is_dlr_match = false; break; } if (is_dl_match) is_dl_match = mat[i + x][j + pattern.size() - x - 1] == pattern[x]; if (is_dlr_match) is_dlr_match = mat[i + x][j + pattern.size() - x - 1] == pattern[pattern.size() - x - 1]; } if ((is_dr_match || is_drr_match) && (is_dl_match || is_dlr_match)) xc += 1; } } fmt::print("Part B: {}\n", xc); } auto aoc24::day04([[maybe_unused]]std::span const& args) -> std::expected { // auto mat = cms::read_text_matnxn("./dat/24/ex/04.txt"); auto mat = cms::read_text_matnxn("./dat/24/re/04.txt"); part_a(mat); part_b(mat); return {}; }