Files
aoc/sol/24/day04.cpp
2024-12-08 23:58:15 +01:00

182 lines
6.0 KiB
C++

#include <fstream>
#include <vector>
#include <algorithm>
#include <ranges>
#include <numeric>
#include <cmath>
#include <utility>
#include "aoc.hpp"
#include "aoc/utils.hpp"
#include "fmt/format.h"
#include "ctre.hpp"
namespace cms {
using vecn = std::vector<std::uint8_t>;
using matnxn = std::vector<vecn>;
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<std::uint8_t>(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<aoc::u8> 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<aoc::u8> 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<char const*> const& args) -> std::expected<void, aoc::error> {
// 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 {};
}