#include "guf_common.h" #include "guf_alloc_libc.h" #include "guf_str.h" /* - Part 1: 1191 (Example: 3) - modular arithmetic - Part 2: 6858 (Example: 6) - modular arithmetic and integer division - note the special case for handling left turns when the dial is at zero. - took me two tries to figure out %) */ guf_allocator g_allocator; guf_libc_alloc_ctx g_allocator_ctx; int solution(guf_str_view input, bool part_two) { guf_str_view linebreak_delim = GUF_CSTR_LIT_TO_VIEW("\n"); guf_str_tok_state tokenizer = guf_str_tok_state_new(input, &linebreak_delim, 1, GUF_STR_TOK_DELIM_OPT_MATCH_LONGEST); const int DIAL_SIZE = 100; // 0 to 99 int cur_dial_pos = 50; int num_zeroes_encountered = 0; while (guf_str_tok_next(&tokenizer, false)) { // For each line. guf_str_view line = guf_str_view_trim_left_ascii(tokenizer.cur_tok); if (line.len < 2) { continue; } const int dir = line.str[0] == 'L' ? -1 : 1; line = guf_str_view_substr(line, 1, line.len - 1); const int num_clicks = guf_str_view_read_uint(&line); if (!part_two) { // Part 1: cur_dial_pos = ( DIAL_SIZE + ((cur_dial_pos + dir * num_clicks) % DIAL_SIZE) ) % DIAL_SIZE; if (cur_dial_pos == 0) { ++num_zeroes_encountered; } } else { // Part 2: int passed_zeroes = 0; if (dir == -1) { // Left (counter-clockwise) turn passed_zeroes = (DIAL_SIZE - cur_dial_pos + num_clicks) / DIAL_SIZE; if (cur_dial_pos == 0 && passed_zeroes > 0 && num_clicks > 0) { // Special case for left turns: Don't count twice if the current position is zero. passed_zeroes -= 1; } } else { // Right (clockwise) turn passed_zeroes = (cur_dial_pos + num_clicks) / DIAL_SIZE; } num_zeroes_encountered += passed_zeroes; cur_dial_pos = ( DIAL_SIZE + ((cur_dial_pos + dir * num_clicks) % DIAL_SIZE) ) % DIAL_SIZE; // Same as in part one } } return num_zeroes_encountered; } int main(int argc, const char **argv) { g_allocator_ctx.zero_init = false; guf_alloc_tracker_init(&g_allocator_ctx.tracker, 1, "Day-1 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 int p1_result = solution(guf_str_view_from_str(&input_str), false); printf("Part one: %d\n", p1_result); const int p2_result = solution(guf_str_view_from_str(&input_str), true); printf("Part two: %d\n", p2_result); guf_str_free(&input_str, NULL); return EXIT_SUCCESS; }