#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // struct FreshRange { // long long left; // long long right; // }; using FreshRange = std::pair; struct PuzzleInput { std::vector freshRanges; std::vector ingredients; }; static auto parseInput(const std::string &filename) -> std::expected { std::ifstream inputF{filename}; if (!inputF) { return std::unexpected{"Some file open error.\n"}; } PuzzleInput puzzleInput{}; std::string puzzleLine{}; while (std::getline(inputF, puzzleLine)) { if (puzzleLine.empty()) { // std::println("Empty string"); break; } auto subParts = std::ranges::to>(std::views::split(puzzleLine, '-')); puzzleInput.freshRanges.emplace_back(std::stoll(subParts[0]), std::stoll(subParts[1])); // std::println("Range: {}", subParts); } while (std::getline(inputF, puzzleLine)) { // std::println("Ingredient: {}", puzzleLine); puzzleInput.ingredients.emplace_back(std::stoll(puzzleLine)); } // std::println("Ranges: {}\nIngredients: {}", puzzleInput.ingredients, puzzleInput.ingredients); return std::move(puzzleInput); } static auto countFreshIngredients(const PuzzleInput &puzzleInput) -> long long { const auto &freshRanges = puzzleInput.freshRanges; const auto &ingredients = puzzleInput.ingredients; long long totalFresh{}; std::println("Ranges: {}\nIngredients: {}", ingredients, ingredients); for (const auto ingredient : ingredients) { std::println("Checking {}", ingredient); for (const auto &range : freshRanges) { if (ingredient >= range.first && ingredient <= range.second) { std::println("{} fits in range: {}:{}", ingredient, range.first, range.second); totalFresh += 1; break; } } } return totalFresh; } static long long countAll(const std::ranges::range auto &ranges) { std::println("Final count:\n\n"); long long bigNum{}; for (const auto &range : ranges) { // std::println("{}:{}", range.first, range.second); if (range == FreshRange(-1, -1)) { continue; } bigNum += range.second - range.first + 1; } return bigNum; } static auto countFreshIngredientsRange(std::vector &ranges) -> long long { std::ranges::sort(ranges); std::list rangeList; rangeList.assign_range(ranges); auto cur = rangeList.begin(); while (true) { auto next = std::next(cur); // std::println("Starting with {}", *cur); if (next == rangeList.end()) { // No need to compare against the end break; } if (cur->second >= next->first) { // std::println("\t Merging! {}", *next); cur->second = std::max(cur->second, next->second); rangeList.erase(next); } else { cur++; } } return countAll(rangeList); } auto main() -> int { auto testCase = parseInput("test_input"); if (testCase) { // auto testResult = countFreshIngredients(*testCase); // std::println("P1 Testcase result: {}", testResult); auto testResultP2 = countFreshIngredientsRange((*testCase).freshRanges); std::println("P2 Testcase result: {}", testResultP2); } else { std::print("{}\n", testCase.error()); } auto realPuzzle = parseInput("puzzle_input"); if (realPuzzle) { // auto realResult = countFreshIngredients(*realPuzzle); // std::println("P1 Real result: {}", realResult); auto realResultP2 = countFreshIngredientsRange((*realPuzzle).freshRanges); std::println("P2 Real result: {}", realResultP2); } else { std::print("{}\n", realPuzzle.error()); } auto tianyi = parseInput("tianyi_input"); if (tianyi) { // auto realResult = countFreshIngredients(*realPuzzle); // std::println("P1 Real result: {}", realResult); auto tianyir = countFreshIngredientsRange((*tianyi).freshRanges); std::println("Tianyi result: {}", tianyir); } else { std::print("{}\n", realPuzzle.error()); } return 0; }