#include "common/getinputpath.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef DATA_FOLDER #error \ "Meson must have defined the DATA_FOLDER somewhere in build scripts. Go check it." #endif // !DATA_FOLDER const std::filesystem::path input_path = get_input_path(DATA_FOLDER); constexpr const char delimiter = ','; struct NumberProfile { long number; bool part1_valid; bool part2_valid; }; [[nodiscard]] NumberProfile is_valid(long id) { std::string id_string = std::to_string(id); bool part1_valid = true; bool part2_valid = true; // repeats 2 times if (id_string.length() % 2 == 0 && part1_valid) { bool invalid = id_string.substr(0, id_string.length() / 2) == id_string.substr(id_string.length() / 2); part1_valid = !invalid; } // repeats more than 2 times if (id_string.length() >= 2 && part2_valid) { auto t = id_string + id_string; part2_valid = t.substr(1, t.length() - 2).find(id_string) == std::string::npos; } return NumberProfile{ .number = id, .part1_valid = part1_valid, .part2_valid = part2_valid, }; } // Ryzen 5 5600G runtime: 1s494ms int main() { std::ifstream input(input_path); if (!input.is_open()) { std::println("Something wrong happened. Can't open file {}", input_path.string()); return 1; } unsigned long long password_part_1 = 0; unsigned long long password_part_2 = 0; // loop hell incoming for (std::string t = ""; std::getline(input, t, delimiter);) { std::println("Checking range {}", t); auto left = t.substr(0, t.find('-')); auto right = t.substr(t.find('-') + 1); auto ids = std::vector(std::stol(right) - std::stol(left)); { auto ids_num = std::vector(std::stol(right) - std::stol(left)); std::ranges::iota(ids_num.begin(), ids_num.end(), std::stol(left)); std::ranges::transform(ids_num, std::back_inserter(ids), [](auto i) { return is_valid(i); }); } auto invalid_ids_part1 = ids | std::ranges::views::filter([](NumberProfile i) { return !i.part1_valid; }) | std::ranges::views::transform([](NumberProfile i) { return i.number; }); auto invalid_ids_part2 = ids | std::ranges::views::filter([](NumberProfile i) { return !i.part2_valid; }) | std::ranges::views::transform([](NumberProfile i) { return i.number; }); auto sum_part1 = std::ranges::fold_left(invalid_ids_part1, 0ULL, std::plus<>{}); password_part_1 += sum_part1; auto sum_part2 = std::ranges::fold_left(invalid_ids_part2, 0ULL, std::plus<>{}); password_part_2 += sum_part2; } std::println("Eureka! {} / {}", password_part_1, password_part_2); return 0; }