finish day 2
This commit is contained in:
112
day2.cpp
112
day2.cpp
@@ -10,26 +10,26 @@
|
|||||||
#include "doctest.h"
|
#include "doctest.h"
|
||||||
|
|
||||||
namespace day2 {
|
namespace day2 {
|
||||||
const std::string sample =
|
const std::string sample =
|
||||||
"11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,"
|
"11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,"
|
||||||
"446443-446449,38593856-38593862,565653-565659,824824821-824824827,"
|
"446443-446449,38593856-38593862,565653-565659,824824821-824824827,"
|
||||||
"2121212118-2121212124";
|
"2121212118-2121212124";
|
||||||
|
|
||||||
struct Range {
|
struct Range {
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
uint64_t end;
|
uint64_t end;
|
||||||
};
|
};
|
||||||
} // namespace day2
|
} // namespace day2
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct std::formatter<day2::Range> : std::formatter<std::string_view> {
|
struct std::formatter<day2::Range> : std::formatter<std::string_view> {
|
||||||
static auto format(const day2::Range &i, std::format_context &ctx) {
|
static auto format(const day2::Range &i, std::format_context &ctx) {
|
||||||
return std::format_to(ctx.out(), "Range[start: {}, end: {}]", i.start,i.end);
|
return std::format_to(ctx.out(), "Range[start: {}, end: {}]", i.start, i.end);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace day2 {
|
namespace day2 {
|
||||||
Range parse_range(std::string_view s) {
|
Range parse_range(std::string_view s) {
|
||||||
std::string_view start;
|
std::string_view start;
|
||||||
std::string_view end;
|
std::string_view end;
|
||||||
|
|
||||||
@@ -41,26 +41,26 @@ namespace day2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Range range;
|
Range range{};
|
||||||
uint64_t parsed;
|
uint64_t parsed;
|
||||||
std::from_chars(start.data(), start.end(), parsed);
|
std::from_chars(start.data(), start.end(), parsed);
|
||||||
range.start = parsed;
|
range.start = parsed;
|
||||||
std::from_chars(end.data(), end.end(), parsed);
|
std::from_chars(end.data(), end.end(), parsed);
|
||||||
range.end = parsed;
|
range.end = parsed;
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t find_divisor(uint64_t n) {
|
size_t find_divisor(const uint64_t n) {
|
||||||
for (size_t i = 1;; i++) {
|
for (size_t i = 1;; i++) {
|
||||||
size_t div = n / std::pow(10, i);
|
size_t div = n / std::pow(10, i);
|
||||||
if (div == 0) {
|
if (div == 0) {
|
||||||
return std::pow(10, (i / 2));
|
return std::pow(10, i / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(0 && "Unreachable");
|
assert(0 && "Unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t count_repetitions(const Range range) {
|
uint64_t count_repetitions(const Range range) {
|
||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
for (uint64_t n = range.start; n <= range.end; n++) {
|
for (uint64_t n = range.start; n <= range.end; n++) {
|
||||||
auto div = find_divisor(n);
|
auto div = find_divisor(n);
|
||||||
@@ -70,23 +70,23 @@ namespace day2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t sum_repetitions(const Range range) {
|
uint64_t sum_repetitions(const Range range) {
|
||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
for (uint64_t n = range.start; n <= range.end; n++) {
|
for (uint64_t n = range.start; n <= range.end; n++) {
|
||||||
auto div = find_divisor(n);
|
const auto div = find_divisor(n);
|
||||||
auto left = n / div;
|
const auto left = n / div;
|
||||||
auto right = n % div;
|
const auto right = n % div;
|
||||||
if (left == right) total += n;
|
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;
|
uint64_t result = 0;
|
||||||
for (const auto range :
|
for (const auto range:
|
||||||
std::views::split(input, ',') | std::views::transform([](auto s) {
|
std::views::split(input, ',') | std::views::transform([](auto s) {
|
||||||
return parse_range(std::string_view(s));
|
return parse_range(std::string_view(s));
|
||||||
})) {
|
})) {
|
||||||
@@ -94,22 +94,41 @@ namespace day2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t sum_repetitions_2(const Range range, std::string& buf) {
|
uint64_t sum_repetitions_2(const Range range, std::string &buf) {
|
||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
for (uint64_t n = range.start; n <= range.end; n++) {
|
for (uint64_t n = range.start; n <= range.end; n++) {
|
||||||
std::format_to(buf, "{}", 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;
|
std::string buf;
|
||||||
buf.reserve(100);
|
buf.reserve(100);
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
for (const auto range :
|
for (const auto range:
|
||||||
std::views::split(input, ',') | std::views::transform([](auto s) {
|
std::views::split(input, ',') | std::views::transform([](auto s) {
|
||||||
return parse_range(std::string_view(s));
|
return parse_range(std::string_view(s));
|
||||||
})) {
|
})) {
|
||||||
@@ -118,35 +137,54 @@ namespace day2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Can parse input") {
|
TEST_CASE("Can parse input") {
|
||||||
auto range = parse_range("11-22");
|
auto range = parse_range("11-22");
|
||||||
CHECK(range.start == 11);
|
CHECK(range.start == 11);
|
||||||
CHECK(range.end == 22);
|
CHECK(range.end == 22);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Solve first sample") {
|
TEST_CASE("Solve first sample") {
|
||||||
CHECK(solve_first(sample) == 1227775554);
|
CHECK(solve_first(sample) == 1227775554);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Solve first input") {
|
TEST_CASE("Solve first input") {
|
||||||
std::ifstream fs("day2input.txt");
|
std::ifstream fs("day2input.txt");
|
||||||
std::stringstream ss{};
|
std::stringstream ss{};
|
||||||
ss << fs.rdbuf();
|
ss << fs.rdbuf();
|
||||||
CHECK(solve_first(ss.str()) == 1227775554);
|
CHECK(solve_first(ss.str()) == 21898734247);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Find divisor works") {
|
TEST_CASE("Find divisor works") {
|
||||||
CHECK(find_divisor(11) == 10);
|
CHECK(find_divisor(11) == 10);
|
||||||
CHECK(find_divisor(1221) == 100);
|
CHECK(find_divisor(1221) == 100);
|
||||||
CHECK(find_divisor(222222) == 1000);
|
CHECK(find_divisor(222222) == 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Count repetition works") {
|
TEST_CASE("Count repetition works") {
|
||||||
CHECK(count_repetitions({.start = 11, .end = 22}) == 2);
|
CHECK(count_repetitions({.start = 11, .end = 22}) == 2);
|
||||||
CHECK(count_repetitions({.start = 1188511880, .end = 1188511890}) == 1);
|
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
|
} // namespace day2
|
||||||
|
|||||||
Reference in New Issue
Block a user