diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index d228f21..b5107ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ cmake-* day1.dSYM -.idea \ No newline at end of file +build +.idea +.cache \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e72f06a..4be6d78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,11 +3,9 @@ project(cpp) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") +set(CMAKE_EXPORT_COMPILE_COMMANDS true) -add_library(cpp STATIC +add_executable(cpp_tests doctest.h - run_tests.cpp - day1.cpp) - -add_executable(cpp_tests run_tests.cpp) -target_link_libraries(cpp_tests PRIVATE cpp) \ No newline at end of file + run_tests.cpp +) diff --git a/day2.cpp b/day2.cpp new file mode 100644 index 0000000..4ae7a9b --- /dev/null +++ b/day2.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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"; + + 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); + } +}; + +namespace day2 { + 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()}; + } + } + + 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) { + for (size_t i = 1;; i++) { + size_t div = n / std::pow(10, i); + if (div == 0) { + return std::pow(10, (i / 2)); + } + } + assert(0 && "Unreachable"); + } + + 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++; + } + + return total; + } + + 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; + } + + return total; + } + + uint64_t solve_first(std::string_view input) { + uint64_t result = 0; + for (const auto range : + std::views::split(input, ',') | std::views::transform([](auto s) { + return parse_range(std::string_view(s)); + })) { + result += sum_repetitions(range); + } + + 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); + } + + return total; + } + + uint64_t solve_second(std::string_view input) { + std::string buf; + buf.reserve(100); + uint64_t result = 0; + for (const auto range : + std::views::split(input, ',') | std::views::transform([](auto s) { + return parse_range(std::string_view(s)); + })) { + result += sum_repetitions_2(range, buf); + buf.clear(); + } + + return result; + } + + + 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 input") { + std::ifstream fs("day2input.txt"); + std::stringstream ss{}; + ss << fs.rdbuf(); + CHECK(solve_first(ss.str()) == 1227775554); + } + + 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); + } + +} // namespace day2 diff --git a/day2input.txt b/day2input.txt new file mode 100644 index 0000000..7b308fc --- /dev/null +++ b/day2input.txt @@ -0,0 +1 @@ +655-1102,2949-4331,885300-1098691,1867-2844,20-43,4382100-4484893,781681037-781860439,647601-734894,2-16,180-238,195135887-195258082,47-64,4392-6414,6470-10044,345-600,5353503564-5353567532,124142-198665,1151882036-1151931750,6666551471-6666743820,207368-302426,5457772-5654349,72969293-73018196,71-109,46428150-46507525,15955-26536,65620-107801,1255-1813,427058-455196,333968-391876,482446-514820,45504-61820,36235767-36468253,23249929-23312800,5210718-5346163,648632326-648673051,116-173,752508-837824 diff --git a/run_tests.cpp b/run_tests.cpp index 716bb2d..c82dc20 100644 --- a/run_tests.cpp +++ b/run_tests.cpp @@ -4,4 +4,5 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "doctest.h" -#include "day1.cpp" \ No newline at end of file +#include "day1.cpp" +#include "day2.cpp"