#include #include #include #include #include #include #include #include "fmt/format.h" using levels_t = std::vector; using reports_t = std::vector; auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int { // constexpr auto filename = "./dat/24/ex/02.txt"; constexpr auto filename = "./tmp.txt"; std::ifstream strm{filename, std::ios::in | std::ios::binary}; if (!strm.is_open()) { fmt::print("Error opening file: {}\n", filename); return 1; } reports_t reports{}; levels_t tmp{}; std::string str{}; while (strm) { auto const c = char(strm.peek()); if (std::isdigit(c)) { str += char(strm.get()); continue; } if (c == ' ' && !str.empty()) { tmp.emplace_back(std::stoi(str)); str.clear(); } if (c == '\n' && !str.empty()) { tmp.emplace_back(std::stoi(str)); reports.emplace_back(std::move(tmp)); str.clear(); } strm.get(); } auto diff = reports | std::views::transform([](auto const& levels) { return levels | std::views::adjacent_transform<2>([](auto const& a, auto const& b) { return b - a; }); }); // condition: all increasing or all decreasing. auto incdec = diff | std::views::filter([](auto const& levels) { auto const n = std::ranges::all_of(levels, [](auto v) { return v < 0; }); auto const p = std::ranges::all_of(levels, [](auto v) { return v > 0; }); return n || p; }); // condition: Any two adjacent levels differ by at least one and at most three. auto adjdiff = incdec | std::views::filter([](auto const& levels){ return std::ranges::all_of(levels, [](auto v) { return std::abs(v) <= 3; }); }); auto const safe_reports = std::ranges::distance(adjdiff); fmt::print("Part A: {}\n", safe_reports); auto lefts = std::views::zip(diff, reports) | std::views::filter([](auto const& pair) { auto const& [d, l] = pair; auto const n = std::ranges::all_of(d, [](auto v) { return v < 0; }); auto const p = std::ranges::all_of(d, [](auto v) { return v > 0; }); return !(n || p); }) | std::views::transform([](auto const& pair) { auto const& [d, l] = pair; return l; }); auto masks = diff | std::views::filter([](auto const& vec) { auto const n = std::ranges::all_of(vec, [](auto v) { return v < 0; }); auto const p = std::ranges::all_of(vec, [](auto v) { return v > 0; }); return !(n || p); }) | std::views::transform([](auto const& vec) { auto const p = std::count_if(std::begin(vec), std::end(vec), [](auto const& v) { return v >= 0; }); auto const n = std::count_if(std::begin(vec), std::end(vec), [](auto const& v) { return v < 0; }); auto mask = vec | std::views::transform([&](auto const& v) { if (p > n) return v >= 0 ? 1 : 0; else return v < 0 ? 1 : 0; }) | std::ranges::to(); mask.push_back(1); return mask; }); auto const remain_reports = std::views::zip(masks, lefts) | std::views::filter([](auto const& pair) { auto const& [mask, level] = pair; auto const n = std::count_if(std::begin(mask), std::end(mask), [](auto const& v) { return v == 0; }); return n == 1; }) | std::views::transform([](auto const& pair){ auto const& [mask, level] = pair; return std::views::zip(mask, level) | std::views::filter([](auto const& pair) { auto const& [m, v] = pair; return m == 1; }) | std::views::transform([](auto const& pair) { auto const& [m, v] = pair; return v; }) | std::ranges::to(); }) | std::ranges::to(); auto rem_diff = remain_reports | std::views::transform([](auto const& vec) { return vec | std::views::adjacent_transform<2>([](auto const& a, auto const& b) { return b - a; }); }); auto safe_rems_vec = rem_diff | std::views::transform([](auto const& vec) { return vec | std::views::filter([](auto const& a) { return std::abs(a) <= 3; }) | std::ranges::to(); }) | std::ranges::to(); auto safe_rems = safe_rems_vec | std::views::filter([](auto const& vec) { return vec.size() > 0; }) | std::views::filter([](auto const& vec) { auto const n = std::ranges::all_of(vec, [](auto v) { return v < 0; }); auto const p = std::ranges::all_of(vec, [](auto v) { return v > 0; }); return n || p; }); auto const safe_reports_rem = std::ranges::distance(safe_rems); // for (auto rep : safe_rems) { // for (auto v : rep) { // fmt::print("{} ", v); // } // fmt::print("\n"); // } fmt::print("Part B: {}\n", safe_reports + safe_reports_rem); return 0; }