83 lines
2.9 KiB
C
83 lines
2.9 KiB
C
#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;
|
|
}
|