From 34339340a1a859630250bce79537986bbb211e8f Mon Sep 17 00:00:00 2001 From: Orfeas <38209077+0xfea5@users.noreply.github.com> Date: Tue, 2 Sep 2025 04:28:00 +0300 Subject: day04: done --- day04/solution.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 day04/solution.cpp (limited to 'day04/solution.cpp') diff --git a/day04/solution.cpp b/day04/solution.cpp new file mode 100644 index 0000000..6fa5ccd --- /dev/null +++ b/day04/solution.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::literals; +namespace views = std::views; +namespace ranges = std::ranges; + +const auto parse_input() { + std::vector grid; + + for (std::string line; std::getline(std::cin, line);) { + grid.push_back(std::move(line)); + } + + return grid; +} + +using IndexPair = std::pair; + +void part1(auto input) { + uint64_t answer{0}; + const int width(input[0].size()); + const int height(input.size()); + + constexpr auto zeros = views::repeat(0, 4); + constexpr auto incr = views::iota(0, 4); + constexpr auto decr = incr | views::transform(std::negate<>{}); + // Pack directions into a tuple because they have different types + constexpr auto directions = std::tuple{ + views::zip(decr, zeros), // top + views::zip(decr, incr), // top-right + views::zip(zeros, incr), // right + views::zip(incr, incr), // bottom-right + views::zip(incr, zeros), // bottom + views::zip(incr, decr), // bottom-left + views::zip(zeros, decr), // left + views::zip(decr, decr), // top-left + }; + + for (const auto [i, j] : + views::cartesian_product(views::iota(0, width), + views::iota(0, height))) { + + // std::apply is needed to unfold the ‘directions’ tuple. + std::apply([=, &answer](auto &&... dirs) { + auto add_offset = [i, j](IndexPair e) { + const auto [di, dj] = e; + return std::tuple{i + di, j + dj}; + }; + + auto in_bounds = [width, height](IndexPair e) -> bool { + const auto [i, j] = e; + return 0 <= i and i < height and 0 <= j and j < width; + }; + + auto get_input_element = [input](IndexPair e) -> char { + const auto [i, j] = e; + return input[i][j]; + }; + + (((answer += ranges::equal(dirs + | views::transform(add_offset) + | views::filter(in_bounds) + | views::transform(get_input_element), "XMAS"sv))), ...); + }, directions); + } + + std::println("{}", answer); +} + +void part2(auto input) { + uint64_t answer{0}; + int width(input[0].size()); + int height(input.size()); + + constexpr size_t window_size = 3; + for (auto &&v_window : input | views::slide(window_size)) { + for (const auto &[r1, r2, r3] : views::zip(v_window[0] | views::slide(window_size), + v_window[1] | views::slide(window_size), + v_window[2] | views::slide(window_size))) { + const std::array diagonals[] = { + {r1[0], r2[1], r3[2]}, + {r3[0], r2[1], r1[2]}, + }; + + answer += ranges::all_of(diagonals, [](const auto &diag) { + return ranges::equal(diag, "MAS"sv) or ranges::equal(diag, "SAM"sv); + }); + } + } + std::println("{}", answer); +} + +int main() { + const auto input = parse_input(); + +#ifndef NO_PART1 + part1(input); +#endif + +#ifndef NO_PART2 + part2(input); +#endif + return 0; +} -- cgit v1.2.3