105 lines
4.4 KiB
C++
105 lines
4.4 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"
|
|
|
|
using namespace std::string_view_literals;
|
|
using namespace aoc::types;
|
|
|
|
auto part_a(std::vector<std::vector<i32>> const& reports) -> void {
|
|
auto const diffvec = reports | std::views::transform([](auto const& levels) {
|
|
return levels | std::views::adjacent_transform<2>([](auto const& a, auto const& b) {
|
|
return b - a;
|
|
}) | std::ranges::to<std::vector>();
|
|
}) | std::ranges::to<std::vector>();
|
|
|
|
auto answer = diffvec | 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; });
|
|
auto const c = std::ranges::all_of(levels, [](auto v) { return std::abs(v) > 0 && std::abs(v) <= 3; });
|
|
return (n || p) && c;
|
|
});
|
|
|
|
auto const sum = std::ranges::distance(answer);
|
|
fmt::print("Part A: {}\n", sum);
|
|
|
|
}
|
|
|
|
auto part_b(std::vector<std::vector<i32>> const& reports) -> void {
|
|
auto const diffvec = reports | std::views::transform([](auto const& levels) {
|
|
return levels | std::views::adjacent_transform<2>([](auto const& a, auto const& b) {
|
|
return b - a;
|
|
}) | std::ranges::to<std::vector>();
|
|
}) | std::ranges::to<std::vector>();
|
|
|
|
auto const test_rule = [](std::vector<i32> 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; });
|
|
auto const c = std::ranges::all_of(levels, [](auto v) { return std::abs(v) > 0 && std::abs(v) <= 3; });
|
|
return (n || p) && c;
|
|
};
|
|
|
|
auto nochange = diffvec | std::views::filter(test_rule);
|
|
|
|
auto unmet = std::views::zip(reports, diffvec) | std::views::filter([](auto const& vecs) {
|
|
auto const& [levels, diffs] = vecs;
|
|
auto const n = std::ranges::all_of(diffs, [](auto v) { return v < 0; });
|
|
auto const p = std::ranges::all_of(diffs, [](auto v) { return v > 0; });
|
|
auto const c = std::ranges::all_of(diffs, [](auto v) { return std::abs(v) > 0 && std::abs(v) <= 3; });
|
|
return !(n || p) || !c;
|
|
}) | std::views::transform([](auto const& vecs) {
|
|
auto const& [levels, diffs] = vecs;
|
|
return levels;
|
|
});
|
|
|
|
auto refit = unmet | std::views::filter([&test_rule](auto const& levels) {
|
|
std::vector<i32> vec{};
|
|
for (std::size_t i = 0; i < levels.size(); ++i) {
|
|
vec = levels;
|
|
vec.erase(std::begin(vec) + std::ptrdiff_t(i));
|
|
vec = vec
|
|
| std::views::adjacent_transform<2>([](auto const& a, auto const& b) { return b - a; })
|
|
| std::ranges::to<std::vector>();
|
|
if (test_rule(vec)) return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
auto const first = std::ranges::distance(nochange);
|
|
auto const second = std::ranges::distance(refit);
|
|
|
|
fmt::print("Part B: {}\n", first + second);
|
|
|
|
}
|
|
|
|
auto aoc24::day02([[maybe_unused]]std::span<char const*> const& args) -> std::expected<void, aoc::error> {
|
|
auto txtres = aoc::read_text("./dat/24/re/02.txt");
|
|
// auto txtres = aoc::read_text("./dat/24/ex/02.txt");
|
|
if (!txtres) return std::unexpected(txtres.error());
|
|
auto const txt = *txtres;
|
|
|
|
auto const reports = txt | std::views::split("\n"sv)
|
|
| std::views::transform([](auto const& str) { return std::string_view(str); })
|
|
| std::views::filter([](auto const& str) { return !str.empty(); })
|
|
| std::views::transform([](auto const& str) {
|
|
return str | std::views::split(" "sv)
|
|
| std::views::filter([](auto str) { return !str.empty(); })
|
|
| std::views::transform([](auto const& num_str) {
|
|
return std::stoi(std::string(std::begin(num_str), std::end(num_str)));
|
|
})
|
|
| std::ranges::to<std::vector>();
|
|
}) | std::ranges::to<std::vector>();
|
|
|
|
part_a(reports);
|
|
part_b(reports);
|
|
|
|
return {};
|
|
}
|