// // Created by postaron on 06/12/23. // #include "problem_1.hpp" #include #include #include #include #include #include #include #include #include namespace pb1 { using namespace std::string_view_literals; constexpr std::string_view digits = "0123456789"; constexpr std::array digitLetters{ "one"sv, "two"sv, "three"sv, "four"sv, "five"sv, "six"sv, "seven"sv, "eight"sv, "nine"sv, }; const std::unordered_map numbersSet{ { "one"sv, '1' }, { "two"sv, '2' }, { "three"sv, '3' }, { "four"sv, '4' }, { "five"sv, '5' }, { "six"sv, '6' }, { "seven"sv, '7' }, { "eight"sv, '8' }, { "nine"sv, '9' }, }; std::optional read_file(const fs::path &problemFile) noexcept { std::ifstream file(problemFile); if (!file.is_open()) { const auto error_state = file.rdstate(); switch (error_state) { case std::ios::badbit: std::cerr << "Fatal I/O error occurred.\n"; break; case std::ios::eofbit: std::cerr << "End of file reached.\n"; break; case std::ios::failbit: std::cerr << "Non-fatal I/O error occurred.\n"; break; default: std::cerr << "impossible to reach.\n"; break; } const auto path_string = problemFile.string(); const auto msg = std::format("Failed to open file {}: ", path_string); std::perror(msg.c_str()); return std::nullopt; } return file; } void part1(const std::string_view &toSearch, std::size_t &result) noexcept { const auto first_digit_pos = toSearch.find_first_of(digits); if (first_digit_pos == std::string::npos) { return; } const auto second_part = toSearch.substr(first_digit_pos); const auto second_digit_pos = second_part.find_last_of(digits) + first_digit_pos; result += (toSearch[first_digit_pos] - '0') * 10 + (toSearch[second_digit_pos] - '0'); } std::size_t solve_problem_part1(const fs::path &problemFile) { auto file_option = read_file(problemFile); if (!file_option) { return 0; } std::ifstream &file = *file_option; std::size_t result = 0; for (std::string line; std::getline(file, line);) { part1(line, result); } return result; } void part2(const std::string_view &toSearch, std::vector &splittedLine, std::size_t &result) noexcept { std::string line_with_numbers, word; line_with_numbers.reserve(toSearch.size()); word.reserve(sizeof("seven") - 1); for (int i = 0; i < toSearch.size(); ++i) { const std::uint32_t nb_characters_remaining = toSearch.size() - i; switch (toSearch[i]) { case 'o': { if (nb_characters_remaining >= digitLetters[0].size()) { word.append(toSearch.substr(i, digitLetters[0].size())); if (numbersSet.contains(word)) { line_with_numbers.push_back(numbersSet.at(word)); } } word.clear(); } break; case 't': { if (nb_characters_remaining >= digitLetters[1].size()) { // TODO: problème si on a two mais là ça ajoute + de caractère… const auto number_two = toSearch.substr(i, digitLetters[1].size()); const auto number_three = [&]() -> std::string_view { const auto tmp = toSearch.substr(i); if (tmp.size() <= digitLetters[2].size()) { return toSearch.substr(i); } else { return toSearch.substr(i, digitLetters[2].size()); } }(); if (numbersSet.contains(number_two) or numbersSet.contains(number_three)) { word.append(numbersSet.contains(number_two) ? number_two : number_three); line_with_numbers.push_back(numbersSet.at(word)); } } word.clear(); } break; case 'f': { // length five and four are equal if (nb_characters_remaining < digitLetters[3].size()) { line_with_numbers.append(toSearch.substr(i)); continue; } word.append(toSearch.substr(i, digitLetters[3].size())); if (!numbersSet.contains(word)) { const auto pos = word.find_first_of(digits); if (pos != std::string::npos) { line_with_numbers.push_back(word[pos]); } } else { line_with_numbers.push_back(numbersSet.at(word)); } word.clear(); } break; case 's': { if (nb_characters_remaining < digitLetters[6].size()) { line_with_numbers.append(toSearch.substr(i)); continue; } const auto number_six = toSearch.substr(i, digitLetters[5].size()); const auto number_seven = toSearch.substr(i, digitLetters[6].size()); if (!numbersSet.contains(number_six) and !numbersSet.contains(number_seven)) { const auto pos = number_seven.find_first_of(digits); if (pos != std::string::npos) { line_with_numbers.push_back(word[pos]); } } else { line_with_numbers.push_back(numbersSet.at(word)); } word.clear(); } break; case 'e': { if (nb_characters_remaining < digitLetters[7].size()) { line_with_numbers.append(toSearch.substr(i)); continue; } word.append(toSearch.substr(i, digitLetters[7].size())); if (!numbersSet.contains(word)) { const auto pos = word.find_first_of(digits); if (pos != std::string::npos) { line_with_numbers.push_back(word[pos]); } } else { line_with_numbers.push_back(numbersSet.at(word)); } word.clear(); } break; case 'n': { if (nb_characters_remaining < digitLetters.back().size()) { line_with_numbers.append(toSearch.substr(i)); continue; } word.append(toSearch.substr(i, digitLetters.back().size())); if (!numbersSet.contains(word)) { const auto pos = word.find_first_of(digits); if (pos != std::string::npos) { line_with_numbers.push_back(word[pos]); } } else { line_with_numbers.push_back(numbersSet.at(word)); } word.clear(); } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': line_with_numbers.push_back(toSearch[i]); break; default: if ((toSearch[i] - '0') < 10) { line_with_numbers.push_back(toSearch[i]); } break; } } if (!line_with_numbers.empty()) { result += (line_with_numbers.front() - '0') * 10 + (line_with_numbers.back() - '0'); } } std::size_t solve_problem_part2(const fs::path &problemFile) { auto file_option = read_file(problemFile); if (!file_option) { return 0; } std::ifstream &file = *file_option; std::vector splitted_line; std::size_t result = 0; for (std::string line; std::getline(file, line);) { part2(line, splitted_line, result); splitted_line.clear(); } return result; } }