From a1d5d359f281cf0652c1c05b18c4767223524465 Mon Sep 17 00:00:00 2001 From: mnerv <24420859+mnerv@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:35:49 +0100 Subject: [PATCH] aoc24: day02b complete --- CMakeLists.txt | 82 +++++++++++------------------ aoc.cpp | 92 ++------------------------------ aoc/{aoc.hpp => utils.hpp} | 3 +- sol/24/CMakeLists.txt | 24 +++++++++ sol/24/aoc.cpp | 34 ++++++++++++ sol/24/aoc.hpp | 40 ++++++++++++++ sol/24/day01.cpp | 68 ++++++++++++++++++++++++ sol/24/day02.cpp | 104 +++++++++++++++++++++++++++++++++++++ sol/24/day03.cpp | 9 ++-- sol/24/day04.cpp | 6 ++- sol/24/day05.cpp | 7 +++ sol/24/day06.cpp | 7 +++ sol/24/day07.cpp | 7 +++ sol/24/day08.cpp | 7 +++ 14 files changed, 342 insertions(+), 148 deletions(-) rename aoc/{aoc.hpp => utils.hpp} (95%) create mode 100644 sol/24/CMakeLists.txt create mode 100644 sol/24/aoc.cpp create mode 100644 sol/24/aoc.hpp create mode 100644 sol/24/day05.cpp create mode 100644 sol/24/day06.cpp create mode 100644 sol/24/day07.cpp create mode 100644 sol/24/day08.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3629181..d69655f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,36 +88,36 @@ else() ) endif() -# set(HEADERS -# aoc/aoc.hpp -# ) -# set(SOURCES "aoc.cpp") -# add_library(aoclib OBJECT ${HEADERS} ${SOURCES}) -# target_include_directories(aoclib -# PUBLIC -# ${PROJECT_SOURCE_DIR} -# PRIVATE -# ${PROJECT_SOURCE_DIR}/aoclib -# ) -# target_compile_features(aoclib PRIVATE cxx_std_23) -# target_compile_options(aoclib PRIVATE ${BASE_OPTIONS}) -# target_compile_definitions(aoclib -# PRIVATE -# ${BASE_DEFINITIONS} -# ) -# target_link_libraries(aoclib -# PUBLIC -# fmt -# utf8cpp -# ctre -# stb::stb -# Threads::Threads -# ) -# source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES}) - set(HEADERS - aoc/aoc.hpp + aoc/utils.hpp ) +set(SOURCES "") +add_library(aoclib OBJECT ${HEADERS} ${SOURCES}) +target_include_directories(aoclib + PUBLIC + ${PROJECT_SOURCE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR}/aoc +) +target_compile_features(aoclib PRIVATE cxx_std_23) +target_compile_options(aoclib PRIVATE ${BASE_OPTIONS}) +target_compile_definitions(aoclib + PRIVATE + ${BASE_DEFINITIONS} +) +target_link_libraries(aoclib + PUBLIC + fmt + utf8cpp + ctre + stb::stb + Threads::Threads +) +source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES}) + +add_subdirectory(sol/24) + +set(HEADERS "") set(SOURCES "aoc.cpp") add_executable(aoc ${HEADERS} ${SOURCES}) target_include_directories(aoc @@ -134,29 +134,7 @@ target_compile_definitions(aoc ) target_link_libraries(aoc PUBLIC - fmt - utf8cpp - ctre - stb::stb - Threads::Threads + aoclib + aoc24 ) source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES}) - -# set(HEADERS "") -# set(SOURCES -# # sol/24/day03.cpp -# sol/24/day04.cpp -# ) -# add_executable(aoc ${HEADERS} ${SOURCES}) -# target_include_directories(aoc PRIVATE ${PROJECT_SOURCE_DIR}) -# target_compile_features(aoc PRIVATE cxx_std_23) -# target_compile_options(aoc PRIVATE ${BASE_OPTIONS}) -# target_compile_definitions(aoc PRIVATE ${BASE_DEFINITIONS}) -# target_link_libraries(aoc -# PRIVATE -# aoclib -# ) -# set_target_properties(aoc PROPERTIES -# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" -# ) -# source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES}) diff --git a/aoc.cpp b/aoc.cpp index b583c8a..3b1066c 100644 --- a/aoc.cpp +++ b/aoc.cpp @@ -10,97 +10,11 @@ #include "fmt/format.h" -#include "aoc/aoc.hpp" - -namespace vfp { -using namespace aoc::types; -using order_rule = std::vector; -} +#include "aoc/utils.hpp" +#include "sol/24/aoc.hpp" auto entry([[maybe_unused]]std::span const& args) -> std::expected { - using namespace std::string_view_literals; - // auto txtres = aoc::read_text("./dat/24/ex/05.txt"); - auto txtres = aoc::read_text("./dat/24/re/05.txt"); - if (!txtres) return std::unexpected(txtres.error()); - auto const txt = *txtres; - - auto const not_empty = [](auto const& str) { return !str.empty(); }; - auto lines = txt | std::views::split("\n"sv) - | std::views::transform([](auto const& str) { return std::string_view(str); }); - - auto rules_str = lines | std::views::take_while(not_empty) - | std::ranges::to(); - auto updates_str = lines | std::views::drop_while(not_empty) - | std::views::drop(1) - | std::views::take_while(not_empty) - | std::ranges::to(); - - // fmt::print("rules:\n"); - // std::ranges::for_each(rules_str, [](auto const& str) { - // fmt::print(" \"{}\"\n", str); - // }); - // fmt::print("\n"); - // - // fmt::print("updates:\n"); - // std::ranges::for_each(updates_str, [](auto const& str) { - // fmt::print(" \"{}\"\n", str); - // }); - - auto order_rules = rules_str | std::views::transform([](auto const& str) { - return str | std::views::split("|"sv) - | std::views::transform([](auto const& num_str) { - return std::stoi(std::string{std::begin(num_str), std::end(num_str)}); - }) | std::ranges::to(); - }) | std::ranges::to(); - - auto updates = updates_str | std::views::transform([](auto const& str) { - return str | std::views::split(","sv) - | std::views::transform([](auto const& num_str) { - return std::stoi(std::string{std::begin(num_str), std::end(num_str)}); - }) | std::ranges::to(); - }) | std::ranges::to(); - - // std::ranges::for_each(order_rules, [](auto const& rule) { - // std::ranges::for_each(rule, [](auto const& page) { - // fmt::print("{} ", page); - // }); - // fmt::print("\n"); - // }); - // - // std::ranges::for_each(updates, [](auto const& update) { - // std::ranges::for_each(update, [](auto const& page) { - // fmt::print("{}, ", page); - // }); - // fmt::print("\n"); - // }); - - auto valid_updates = updates | std::views::filter([&](auto const& pages) { - return std::ranges::all_of(order_rules, [&](auto const& rule) { - auto const a = std::ranges::find(pages, rule[0]); - auto const b = std::ranges::find(pages, rule[1]); - return a < b || a == std::end(pages) || b == std::end(pages) || a == b; - }); - }); - - // std::ranges::for_each(valid_updates, [](auto const& update){ - // std::ranges::for_each(update, [](auto const& page) { - // fmt::print("{}, ", page); - // }); - // fmt::print("\n"); - // }); - - auto mids = valid_updates | std::views::transform([](auto const& updates) { - return *std::ranges::next(std::begin(updates), updates.size() / 2); - }); - - // std::ranges::for_each(mids, [](auto const& mid) { - // fmt::print("{}\n", mid); - // }); - - auto const sum = std::accumulate(std::begin(mids), std::end(mids), 0); - fmt::print("Part A: {}\n", sum); - - return {}; + return aoc24::entry(args); } auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int { diff --git a/aoc/aoc.hpp b/aoc/utils.hpp similarity index 95% rename from aoc/aoc.hpp rename to aoc/utils.hpp index d06f1db..596b410 100644 --- a/aoc/aoc.hpp +++ b/aoc/utils.hpp @@ -70,7 +70,7 @@ inline auto make_error(std::string const& str, std::errc ec) -> std::unexpected< return std::unexpected(error{str, std::make_error_code(ec)}); } -auto read_text(std::string const& path) -> std::expected { +inline auto read_text(std::string const& path) -> std::expected { std::fstream strm(path, std::ios::in | std::ios::binary); if (!strm.is_open()) return aoc::make_error(path, std::errc::no_such_file_or_directory); @@ -86,5 +86,4 @@ template using vec = std::vector; } - #endif // !AOC_AOC_HPP diff --git a/sol/24/CMakeLists.txt b/sol/24/CMakeLists.txt new file mode 100644 index 0000000..1452b3d --- /dev/null +++ b/sol/24/CMakeLists.txt @@ -0,0 +1,24 @@ +set(HEADERS + aoc.hpp +) +set(SOURCES + "aoc.cpp" + "day01.cpp" + "day02.cpp" + "day03.cpp" + "day04.cpp" + "day05.cpp" + "day06.cpp" + "day07.cpp" + "day08.cpp" +) +add_library(aoc24 STATIC ${HEADERS} ${SOURCES}) +target_include_directories(aoc24 + PRIVATE + ${PROJECT_SOURCE_DIR} +) +target_compile_features(aoc24 PRIVATE cxx_std_23) +target_compile_options(aoc24 PRIVATE ${BASE_OPTIONS}) +target_compile_definitions(aoc24 PRIVATE ${BASE_DEFINITIONS}) +target_link_libraries(aoc24 PRIVATE aoclib) +source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES}) diff --git a/sol/24/aoc.cpp b/sol/24/aoc.cpp new file mode 100644 index 0000000..5abaa2f --- /dev/null +++ b/sol/24/aoc.cpp @@ -0,0 +1,34 @@ +#include +#include + +#include "aoc.hpp" +#include "ctre.hpp" + +namespace aoc24 { +auto entry([[maybe_unused]]std::span const& args) -> std::expected { + using namespace aoc::types; + + u32 day = 1; + if (args.size() > 1) { + if (ctre::match<"^[0-9]+$">(args[1])) + day = std::stoul(args[1]); + else + fmt::print(stderr, "arg: {} is not a number\n", args[1]); + } + + switch (day) { + case 1: return day01(args); + case 2: return day02(args); + case 3: return day03(args); + case 4: return day04(args); + case 5: return day05(args); + case 6: return day06(args); + case 7: return day07(args); + case 8: return day08(args); + default: + return aoc::make_error(fmt::format("day {}", day), std::errc::not_supported); + } + + return {}; +} +} diff --git a/sol/24/aoc.hpp b/sol/24/aoc.hpp new file mode 100644 index 0000000..5cbad54 --- /dev/null +++ b/sol/24/aoc.hpp @@ -0,0 +1,40 @@ +#ifndef SOL_24_AOC_HPP +#define SOL_24_AOC_HPP + +#include +#include +#include "aoc/utils.hpp" + +#include "fmt/format.h" + +namespace aoc24 { +auto entry(std::span const& args) -> std::expected; + +auto day01(std::span const& args) -> std::expected; +auto day02(std::span const& args) -> std::expected; +auto day03(std::span const& args) -> std::expected; +auto day04(std::span const& args) -> std::expected; +auto day05(std::span const& args) -> std::expected; +auto day06(std::span const& args) -> std::expected; +auto day07(std::span const& args) -> std::expected; +auto day08(std::span const& args) -> std::expected; +auto day09(std::span const& args) -> std::expected; +auto day10(std::span const& args) -> std::expected; +auto day11(std::span const& args) -> std::expected; +auto day12(std::span const& args) -> std::expected; +auto day13(std::span const& args) -> std::expected; +auto day14(std::span const& args) -> std::expected; +auto day15(std::span const& args) -> std::expected; +auto day16(std::span const& args) -> std::expected; +auto day17(std::span const& args) -> std::expected; +auto day18(std::span const& args) -> std::expected; +auto day19(std::span const& args) -> std::expected; +auto day20(std::span const& args) -> std::expected; +auto day21(std::span const& args) -> std::expected; +auto day22(std::span const& args) -> std::expected; +auto day23(std::span const& args) -> std::expected; +auto day24(std::span const& args) -> std::expected; +auto day25(std::span const& args) -> std::expected; +} + +#endif diff --git a/sol/24/day01.cpp b/sol/24/day01.cpp index e69de29..de146cc 100644 --- a/sol/24/day01.cpp +++ b/sol/24/day01.cpp @@ -0,0 +1,68 @@ +#include +#include + +#include "aoc.hpp" +#include "aoc/utils.hpp" +#include "fmt/format.h" + +auto aoc24::day01([[maybe_unused]]std::span const& args) -> std::expected { + constexpr auto filename = "./dat/24/re/01.txt"; + std::ifstream strm{filename, std::ios::in}; + if (!strm.is_open()) { + return aoc::make_error( + fmt::format("Error opening file: {}\n", filename), + std::errc::file_exists + ); + } + + std::vector a{}; + std::vector b{}; + + std::string str{}; + while (strm) { + auto const c = char(strm.peek()); + if (std::isdigit(c)) { + str += char(strm.get()); + continue; + } + if (c == ' ') { + if (!str.empty()) { + a.emplace_back(std::stoi(str)); + str.clear(); + } + } + if (c == '\n') { + if (!str.empty()) { + b.emplace_back(std::stoi(str)); + str.clear(); + } + } + [[discard]]strm.get(); + } + + fmt::print("a: {}, b: {}\n", a.size(), b.size()); + + std::sort(std::begin(a), std::end(a)); + std::sort(std::begin(b), std::end(b)); + + auto diff_view = std::views::zip(a, b) | std::views::transform([](auto const& p) { + auto const [x, y] = p; + return x > y ? x - y : y - x; + }); + auto const sum = std::accumulate(std::begin(diff_view), std::end(diff_view), 0); + + fmt::print("Part A: {}\n", std::abs(sum)); + + auto values = a | std::views::transform([&b](auto v) { + return std::pair{v, b | std::views::filter([v](auto c) { + return v == c; // Filter elements in `b` equal to `v` + }) | std::ranges::to()}; + }) | std::ranges::to(); + + auto const meow = std::accumulate(std::begin(values), std::end(values), 0, [](auto const acc, auto const& pair) { + return acc + std::int32_t(pair.first * pair.second.size()); + }); + + fmt::print("Part B: {}\n", meow); + return {}; +} diff --git a/sol/24/day02.cpp b/sol/24/day02.cpp index e69de29..60f8ee4 100644 --- a/sol/24/day02.cpp +++ b/sol/24/day02.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include + +#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> 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::ranges::to(); + + 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> 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::ranges::to(); + + auto const test_rule = [](std::vector 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 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(); + 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 const& args) -> std::expected { + 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::ranges::to(); + + part_a(reports); + part_b(reports); + + return {}; +} diff --git a/sol/24/day03.cpp b/sol/24/day03.cpp index 720f85e..31836c6 100644 --- a/sol/24/day03.cpp +++ b/sol/24/day03.cpp @@ -3,8 +3,10 @@ #include #include #include +#include -#include "aoc/aoc.hpp" +#include "aoc.hpp" +#include "aoc/utils.hpp" #include "fmt/format.h" #include "ctre.hpp" @@ -157,8 +159,8 @@ private: if (peek() == '\n') { peek_consume(); m_line = m_line + 1; - m_col = 1; str += "\\n"; + m_col = 1; auto const& type = token_type::invalid; return token(str, type, token_type_category(type), m_line, col); } @@ -387,7 +389,7 @@ private: }; } -auto aoc::entry([[maybe_unused]]std::vector const& args) -> void { +auto aoc24::day03([[maybe_unused]]std::span const& args) -> std::expected { npr::lexer lexer{"./dat/24/re/03.txt"}; npr::parser parser{}; auto const tokens = lexer.tokenize(); @@ -438,5 +440,6 @@ auto aoc::entry([[maybe_unused]]std::vector const& args) -> vo auto const sumb = std::accumulate(std::begin(opb), std::end(opb), 0); fmt::print("Part B: {}\n", sumb); + return {}; } diff --git a/sol/24/day04.cpp b/sol/24/day04.cpp index 323a162..5a43a1c 100644 --- a/sol/24/day04.cpp +++ b/sol/24/day04.cpp @@ -6,7 +6,8 @@ #include #include -#include "aoc/aoc.hpp" +#include "aoc.hpp" +#include "aoc/utils.hpp" #include "fmt/format.h" #include "ctre.hpp" @@ -121,7 +122,7 @@ auto read_text_matnxn(std::string const& path) -> matnxn { } } -auto aoc::entry([[maybe_unused]]std::span const& args) -> void { +auto aoc24::day04([[maybe_unused]]std::span const& args) -> std::expected { auto source = cms::read_text_matnxn("./dat/24/ex/04.txt"); cms::vecn hpat{'X', 'M', 'A', 'S'}; @@ -155,5 +156,6 @@ auto aoc::entry([[maybe_unused]]std::span const& args) -> void { // } // fmt::print("\n"); // } + return {}; } diff --git a/sol/24/day05.cpp b/sol/24/day05.cpp new file mode 100644 index 0000000..2a0de91 --- /dev/null +++ b/sol/24/day05.cpp @@ -0,0 +1,7 @@ +#include "aoc.hpp" +#include "aoc/utils.hpp" +#include "fmt/format.h" + +auto aoc24::day05([[maybe_unused]]std::span const& args) -> std::expected { + return aoc::make_error("not implemented", std::errc::not_supported); +} diff --git a/sol/24/day06.cpp b/sol/24/day06.cpp new file mode 100644 index 0000000..35887dd --- /dev/null +++ b/sol/24/day06.cpp @@ -0,0 +1,7 @@ +#include "aoc.hpp" +#include "aoc/utils.hpp" +#include "fmt/format.h" + +auto aoc24::day06([[maybe_unused]]std::span const& args) -> std::expected { + return aoc::make_error("not implemented", std::errc::not_supported); +} diff --git a/sol/24/day07.cpp b/sol/24/day07.cpp new file mode 100644 index 0000000..2870072 --- /dev/null +++ b/sol/24/day07.cpp @@ -0,0 +1,7 @@ +#include "aoc.hpp" +#include "aoc/utils.hpp" +#include "fmt/format.h" + +auto aoc24::day07([[maybe_unused]]std::span const& args) -> std::expected { + return aoc::make_error("not implemented", std::errc::not_supported); +} diff --git a/sol/24/day08.cpp b/sol/24/day08.cpp new file mode 100644 index 0000000..a247dba --- /dev/null +++ b/sol/24/day08.cpp @@ -0,0 +1,7 @@ +#include "aoc.hpp" +#include "aoc/utils.hpp" +#include "fmt/format.h" + +auto aoc24::day08([[maybe_unused]]std::span const& args) -> std::expected { + return aoc::make_error("not implemented", std::errc::not_supported); +}