From 05a5bc27ade4e77ae7ca6ccf67c1cb15cd1b0613 Mon Sep 17 00:00:00 2001 From: Grant Horner Date: Tue, 2 Dec 2025 17:03:54 -0500 Subject: [PATCH] finish day 2 --- day2.cpp | 224 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 131 insertions(+), 93 deletions(-) diff --git a/day2.cpp b/day2.cpp index 4ae7a9b..f05d9eb 100644 --- a/day2.cpp +++ b/day2.cpp @@ -10,143 +10,181 @@ #include "doctest.h" namespace day2 { - const std::string sample = - "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528," - "446443-446449,38593856-38593862,565653-565659,824824821-824824827," - "2121212118-2121212124"; +const std::string sample = + "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528," + "446443-446449,38593856-38593862,565653-565659,824824821-824824827," + "2121212118-2121212124"; - struct Range { - uint64_t start; - uint64_t end; - }; +struct Range { + uint64_t start; + uint64_t end; +}; } // namespace day2 template<> struct std::formatter : std::formatter { - static auto format(const day2::Range &i, std::format_context &ctx) { - return std::format_to(ctx.out(), "Range[start: {}, end: {}]", i.start,i.end); - } + static auto format(const day2::Range &i, std::format_context &ctx) { + return std::format_to(ctx.out(), "Range[start: {}, end: {}]", i.start, i.end); + } }; namespace day2 { - Range parse_range(std::string_view s) { - std::string_view start; - std::string_view end; +Range parse_range(std::string_view s) { + std::string_view start; + std::string_view end; - for (size_t i = 0; i < s.size(); i++) { - const char c = s[i]; - if (c == '-') { - start = {s.data(), i}; - end = {s.data() + i + 1, s.size() - start.size()}; - } - } + for (size_t i = 0; i < s.size(); i++) { + const char c = s[i]; + if (c == '-') { + start = {s.data(), i}; + end = {s.data() + i + 1, s.size() - start.size()}; + } + } - Range range; - uint64_t parsed; - std::from_chars(start.data(), start.end(), parsed); - range.start = parsed; - std::from_chars(end.data(), end.end(), parsed); - range.end = parsed; - return range; - } + Range range{}; + uint64_t parsed; + std::from_chars(start.data(), start.end(), parsed); + range.start = parsed; + std::from_chars(end.data(), end.end(), parsed); + range.end = parsed; + return range; +} - size_t find_divisor(uint64_t n) { +size_t find_divisor(const uint64_t n) { for (size_t i = 1;; i++) { - size_t div = n / std::pow(10, i); - if (div == 0) { - return std::pow(10, (i / 2)); - } + size_t div = n / std::pow(10, i); + if (div == 0) { + return std::pow(10, i / 2); + } } - assert(0 && "Unreachable"); - } + assert(0 && "Unreachable"); +} - uint64_t count_repetitions(const Range range) { - uint64_t total = 0; +uint64_t count_repetitions(const Range range) { + uint64_t total = 0; for (uint64_t n = range.start; n <= range.end; n++) { - auto div = find_divisor(n); - auto left = n / div; - auto right = n % div; - if (left == right) total++; + auto div = find_divisor(n); + auto left = n / div; + auto right = n % div; + if (left == right) total++; } - return total; - } + return total; +} - uint64_t sum_repetitions(const Range range) { - uint64_t total = 0; +uint64_t sum_repetitions(const Range range) { + uint64_t total = 0; for (uint64_t n = range.start; n <= range.end; n++) { - auto div = find_divisor(n); - auto left = n / div; - auto right = n % div; - if (left == right) total += n; + const auto div = find_divisor(n); + const auto left = n / div; + const auto right = n % div; + if (left == right) total += n; } - return total; - } + return total; +} - uint64_t solve_first(std::string_view input) { +uint64_t solve_first(std::string_view input) { uint64_t result = 0; - for (const auto range : + for (const auto range: std::views::split(input, ',') | std::views::transform([](auto s) { - return parse_range(std::string_view(s)); + return parse_range(std::string_view(s)); })) { - result += sum_repetitions(range); + result += sum_repetitions(range); } - return result; - } + return result; +} - uint64_t sum_repetitions_2(const Range range, std::string& buf) { - uint64_t total = 0; - for (uint64_t n = range.start; n <= range.end; n++) { - std::format_to(buf, "{}", n); +uint64_t sum_repetitions_2(const Range range, std::string &buf) { + uint64_t total = 0; + for (uint64_t n = range.start; n <= range.end; n++) { + std::format_to(std::back_inserter(buf), "{}", n); + size_t size = buf.size(); + for (int i = 0; i < size; ++i) { + if (size % i != 0 || size / i == 1) continue; + std::string_view first_partition(buf.data(), i); + bool all_equal = true; + for (int j = i; j < size; j += i) { + std::string_view partition(buf.data() + j, i); + if (partition != first_partition) { + all_equal = false; + break; + } + } + + if (all_equal) { + total += n; + break; + } + } + buf.clear(); } - return total; - } + return total; +} - uint64_t solve_second(std::string_view input) { +uint64_t solve_second(std::string_view input) { std::string buf; - buf.reserve(100); + buf.reserve(100); uint64_t result = 0; - for (const auto range : + for (const auto range: std::views::split(input, ',') | std::views::transform([](auto s) { - return parse_range(std::string_view(s)); + return parse_range(std::string_view(s)); })) { - result += sum_repetitions_2(range, buf); - buf.clear(); + result += sum_repetitions_2(range, buf); + buf.clear(); } - return result; - } + return result; +} - TEST_CASE("Can parse input") { - auto range = parse_range("11-22"); - CHECK(range.start == 11); - CHECK(range.end == 22); - } +TEST_CASE("Can parse input") { + auto range = parse_range("11-22"); + CHECK(range.start == 11); + CHECK(range.end == 22); +} - TEST_CASE("Solve first sample") { - CHECK(solve_first(sample) == 1227775554); - } +TEST_CASE("Solve first sample") { + CHECK(solve_first(sample) == 1227775554); +} - TEST_CASE("Solve first input") { +TEST_CASE("Solve first input") { std::ifstream fs("day2input.txt"); std::stringstream ss{}; - ss << fs.rdbuf(); - CHECK(solve_first(ss.str()) == 1227775554); - } + ss << fs.rdbuf(); + CHECK(solve_first(ss.str()) == 21898734247); +} - TEST_CASE("Find divisor works") { - CHECK(find_divisor(11) == 10); - CHECK(find_divisor(1221) == 100); - CHECK(find_divisor(222222) == 1000); - } +TEST_CASE("Find divisor works") { + CHECK(find_divisor(11) == 10); + CHECK(find_divisor(1221) == 100); + CHECK(find_divisor(222222) == 1000); +} - TEST_CASE("Count repetition works") { - CHECK(count_repetitions({.start = 11, .end = 22}) == 2); - CHECK(count_repetitions({.start = 1188511880, .end = 1188511890}) == 1); - } +TEST_CASE("Count repetition works") { + CHECK(count_repetitions({.start = 11, .end = 22}) == 2); + CHECK(count_repetitions({.start = 1188511880, .end = 1188511890}) == 1); +} + +TEST_CASE("sum_repetitions_2") { + std::string buf; + buf.reserve(100); + CHECK(sum_repetitions_2({95, 115}, buf) == 210); + buf.clear(); + CHECK(sum_repetitions_2({998, 1012}, buf) == 999 + 1010); +} + +TEST_CASE("Solves second sample") { + CHECK(solve_second(sample) == 4174379265); +} + +TEST_CASE("Solves second input") { + std::ifstream fs("day2input.txt"); + std::stringstream ss{}; + ss << fs.rdbuf(); + CHECK(solve_second(ss.view()) == 28915664389); +} } // namespace day2