From e878231d528feeb72fc509fc873fe6bd6c473eae Mon Sep 17 00:00:00 2001 From: zeichensystem <83899451+zeichensystem@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:19:54 +0100 Subject: [PATCH] Solve Day 02 Part 1 --- CMakeLists.txt | 4 +- day-02/day-02.c | 117 +++++++++++++++++++++++++++++++++++++++ input/day-02-example.txt | 3 + libguf/src/guf_str.h | 38 +++++++++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 day-02/day-02.c create mode 100644 input/day-02-example.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index e914fba..e0eb1b6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ if (ipo_available AND (NOT CMAKE_BUILD_TYPE MATCHES Debug) AND (NOT CMAKE_BUILD_ message("-- IPO enabled") endif() -set(TARGETS day-01) # Add the other days as you please. +set(TARGETS day-01 day-02) # Add the other days as you please. list(LENGTH TARGETS NUM_TARGETS) @@ -72,11 +72,13 @@ endforeach(current_target) add_custom_target("run-all" DEPENDS ${TARGETS} COMMAND day-01 ${CMAKE_CURRENT_SOURCE_DIR}/input/day-01.txt + COMMAND day-01 ${CMAKE_CURRENT_SOURCE_DIR}/input/day-02.txt WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) add_custom_target("run-all-examples" DEPENDS ${TARGETS} COMMAND day-01 ${CMAKE_CURRENT_SOURCE_DIR}/input/day-01-example.txt + COMMAND day-02 ${CMAKE_CURRENT_SOURCE_DIR}/input/day-02-example.txt WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) diff --git a/day-02/day-02.c b/day-02/day-02.c new file mode 100644 index 0000000..b6d1581 --- /dev/null +++ b/day-02/day-02.c @@ -0,0 +1,117 @@ +#include "guf_common.h" +#include "guf_alloc_libc.h" +#include "guf_str.h" +#include "guf_math.h" + +/* + - Part 1: 54234399924 (Example: 1227775554) + + - Part 2: (Example: ) +*/ + +guf_allocator g_allocator; +guf_libc_alloc_ctx g_allocator_ctx; + +typedef struct id_range { + uint64_t start, end; +} id_range; + +bool read_id_range(guf_str_view *str, id_range *result) +{ + guf_str_view start_str = guf_str_view_pop_split(str, GUF_CSTR_LIT_TO_VIEW("-")); + guf_str_view end_str = guf_str_view_pop_split(str, GUF_CSTR_LIT_TO_VIEW(",")); + + start_str = guf_str_view_trim_left_ascii(start_str); + end_str = guf_str_view_trim_left_ascii(end_str); + + if (start_str.len <= 0 || end_str.len <= 0) { + return false; + } + + uint64_t start = guf_str_view_read_u64(&start_str); + uint64_t end = guf_str_view_read_u64(&end_str); + + result->start = start; + result->end = end; + + return true; +} + +uint64_t pow_10(int exp) +{ + GUF_ASSERT(exp >= 0); + uint64_t res = 1; + while (exp--) { + res *= 10u; + } + return res; +} + +uint64_t solution(guf_str_view input, bool part_two) +{ + uint64_t invalid_id_sum = 0; + + id_range range; + guf_str start_str, end_str; + guf_str_init_empty(&start_str, &g_allocator); + guf_str_init_empty(&end_str, &g_allocator); + + while (read_id_range(&input, &range)) { + guf_str_append_u64(&start_str, range.start); + guf_str_append_u64(&end_str, range.end); + const int n_digits_start = (int)guf_str_len(&start_str); + const int n_digits_end = (int)guf_str_len(&end_str); + + // Generate all pairs of one, two, three, ... digits (without leading zeroes) + for (int half_n_digits = 1; half_n_digits <= 10; ++half_n_digits) { + if (half_n_digits * 2 > n_digits_end) { + break; + } else if (half_n_digits * 2 < n_digits_start) { + continue; + } + + const uint64_t min_half = pow_10(half_n_digits - 1); + const uint64_t max_half = pow_10(half_n_digits) - 1; + + for (uint64_t cur_half = min_half; cur_half <= max_half; ++cur_half) { + uint64_t id = cur_half * pow_10(half_n_digits) + cur_half; + if (id > range.end) { + break; + } else if (id >= range.start) { + invalid_id_sum += id; + } + } + } + + guf_str_substr(&start_str, 0, 0); + guf_str_substr(&end_str, 0, 0); + } + + return invalid_id_sum; +} + +int main(int argc, const char **argv) +{ + g_allocator_ctx.zero_init = false; + guf_alloc_tracker_init(&g_allocator_ctx.tracker, 1, "Day-2 heap allocator", NULL, stderr); + guf_libc_allocator_init(&g_allocator, &g_allocator_ctx); + + if (argc < 2) { + printf("No input file given.\n"); + return EXIT_FAILURE; + } + + guf_str input_str = GUF_STR_UNINITIALISED; + guf_str_init_empty(&input_str, &g_allocator); + guf_str_append_file(&input_str, argv[1]); + + const uint64_t p1_result = solution(guf_str_view_from_str(&input_str), false); + printf("Part 1: %" PRIu64 "\n", p1_result); + + // const uint64_t p2_result = solution(guf_str_view_from_str(&input_str), true); + // printf("Part 2: %" PRIu64 "\n", p2_result); + + guf_str_free(&input_str, NULL); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/input/day-02-example.txt b/input/day-02-example.txt new file mode 100644 index 0000000..b3dc7c4 --- /dev/null +++ b/input/day-02-example.txt @@ -0,0 +1,3 @@ +11-22,95-115,998-1012,1188511880-1188511890,222220-222224, +1698522-1698528,446443-446449,38593856-38593862,565653-565659, +824824821-824824827,2121212118-2121212124 \ No newline at end of file diff --git a/libguf/src/guf_str.h b/libguf/src/guf_str.h index 8bb9419..7de9ee0 100755 --- a/libguf/src/guf_str.h +++ b/libguf/src/guf_str.h @@ -129,6 +129,8 @@ GUF_STR_KWRDS guf_str_tok_state guf_str_tok_state_new(guf_str_view str, guf_str_ GUF_STR_KWRDS bool guf_str_tok_next(guf_str_tok_state *state, bool preserve_delims); GUF_STR_KWRDS unsigned guf_str_view_read_uint(guf_str_view *sv); // TODO: Handle overflow, signs etc. +GUF_STR_KWRDS uint_least64_t guf_str_view_read_u64(guf_str_view *sv); + // 2.) guf_str: @@ -215,6 +217,9 @@ GUF_STR_KWRDS guf_str *guf_str_append(guf_str *str, guf_str_view sv); GUF_STR_KWRDS ptrdiff_t guf_str_try_append_file(guf_str *to_append, const char *fname, guf_err *err); GUF_STR_KWRDS ptrdiff_t guf_str_append_file(guf_str *to_append, const char *fname); +// Append ints: +GUF_STR_KWRDS guf_str *guf_str_append_u64(guf_str *str, uint_least64_t n); + // Return a pointer to the null-terminated char array representing the string (works like std::string::c_str in C++) GUF_STR_KWRDS const char *guf_str_const_cstr(const guf_str *str); GUF_STR_KWRDS char *guf_str_try_get_cstr(guf_str *str, guf_err *err); // Error if str is readonly. @@ -1188,6 +1193,27 @@ GUF_STR_KWRDS ptrdiff_t guf_str_append_file(guf_str *to_append, const char *fna } +GUF_STR_KWRDS guf_str *guf_str_append_u64(guf_str *str, uint_least64_t n) { + + char buf[20] = {'\0'}; + int start_idx = GUF_ARR_SIZE(buf); + int num_digits = 0; + do { + GUF_ASSERT(start_idx > 0); + char c = (n % 10) + '0'; + buf[--start_idx] = c; + ++num_digits; + } while ((n = n / 10)); + + GUF_ASSERT(num_digits == (int)GUF_ARR_SIZE(buf) - start_idx); + + const guf_str_view num_sv = (guf_str_view) {.str = buf + start_idx, .len = num_digits}; + + return guf_str_append(str, num_sv); +} + + + GUF_STR_KWRDS guf_str *guf_str_try_substr(guf_str *str, ptrdiff_t pos, ptrdiff_t count, guf_err *err) { GUF_ASSERT(guf_str_is_valid(str)); @@ -1584,6 +1610,18 @@ GUF_STR_KWRDS unsigned guf_str_view_read_uint(guf_str_view *sv) return res; } +GUF_STR_KWRDS uint_least64_t guf_str_view_read_u64(guf_str_view *sv) +{ // TODO: Handle overflow etc. + uint_least64_t res = 0; + while (sv->len && sv->str[0] >= '0' && sv->str[0] <= '9') { + res *= 10; + res += (sv->str[0] - '0'); + sv->len -= 1; + sv->str = sv->len > 0 ? sv->str + 1 : NULL; + } + return res; +} + #undef GUF_STR_IMPL #undef GUF_STR_IMPL_STATIC #endif /* end impl */