This commit is contained in:
2024-12-05 21:22:19 +01:00
parent cc23753573
commit b6c66136f7
14 changed files with 452 additions and 0 deletions

200
src/01.c Normal file
View File

@@ -0,0 +1,200 @@
#include <common.h>
#include <arena.h>
#include <buffer.h>
#include <syscall.h>
#define BUFFER_SIZE 4096UL
#define ARENA_CAPACITY 2147483648UL
typedef enum parser_state {
parser_state_left,
parser_state_whitespace,
parser_state_right,
parser_state_eol,
} parser_state;
typedef struct parser {
i32 left;
i32 right;
parser_state state;
} parser;
arena left_arena;
arena right_arena;
arena left_occurences_arena;
arena right_occurences_arena;
usize number_pair_count = 0;
i32 max_left = -1;
i32 max_right = -1;
void parser_process(parser* parser, const c8* ptr, usize len);
void interpreter_process(i32 left, i32 right);
bool is_digit(c8 c);
void insert_sort(i32* ptr, usize len);
void println_u64(u64 value);
i32 main(i32 argc, char *argv[])
{
c8* buffer = buffer_init(BUFFER_SIZE);
left_arena = arena_init(ARENA_CAPACITY);
right_arena = arena_init(ARENA_CAPACITY);
left_occurences_arena = arena_init(ARENA_CAPACITY);
right_occurences_arena = arena_init(ARENA_CAPACITY);
usize buffer_ptr = 0;
isize bytes_read = 0;
parser parser = {0};
while ((bytes_read = read(stdin, &buffer[buffer_ptr], BUFFER_SIZE)) > 0) {
parser_process(&parser, &buffer[buffer_ptr], bytes_read);
buffer_ptr = (buffer_ptr + bytes_read) % BUFFER_SIZE;
}
i32 *left_array = left_arena.ptr;
i32 *right_array = right_arena.ptr;
insert_sort(left_array, number_pair_count);
insert_sort(right_array, number_pair_count);
// Calculate part I
u64 cumdiff = 0;
for (usize i = 0; i < number_pair_count; ++i)
{
i32 diff = left_array[i] - right_array[i];
if (diff < 0) {
diff = -diff;
}
cumdiff += diff;
}
println_u64(cumdiff);
// Calculate part II
u16 *right_occurences = right_occurences_arena.ptr;
u64 similarity = 0;
for (usize i = 0; i < number_pair_count; ++i)
{
i32 left = left_array[i];
if (left > max_right) continue;
similarity += (u64)left * (u64)right_occurences[left];
}
println_u64(similarity);
return 0;
}
void parser_process(parser* parser, const c8* ptr, usize len)
{
const c8* end = &ptr[len];
while (ptr < end) {
c8 c = *ptr;
switch (parser->state) {
case parser_state_left:
if (is_digit(c)) {
parser->left = parser->left * 10 + (c - '0');
ptr += 1;
} else {
parser->state = parser_state_whitespace;
}
break;
case parser_state_whitespace:
if (is_digit(c)) {
parser->state = parser_state_right;
} else {
ptr += 1;
}
break;
case parser_state_right:
if (is_digit(c)) {
parser->right = parser->right * 10 + (c - '0');
ptr += 1;
} else {
parser->state = parser_state_eol;
interpreter_process(parser->left, parser->right);
parser->left = 0;
parser->right = 0;
}
break;
case parser_state_eol:
if (is_digit(c)) {
parser->state = parser_state_left;
} else {
ptr += 1;
}
break;
}
}
}
void interpreter_process(i32 left, i32 right)
{
i32 *left_array = left_arena.ptr;
i32 *right_array = right_arena.ptr;
u16 *left_occurences = left_occurences_arena.ptr;
u16 *right_occurences = right_occurences_arena.ptr;
ARENA_ENSURE(i32, &left_arena, number_pair_count + 1);
ARENA_ENSURE(i32, &right_arena, number_pair_count + 1);
ARENA_ENSURE(u16, &left_occurences_arena, left + 1);
ARENA_ENSURE(u16, &right_occurences_arena, right + 1);
left_array[number_pair_count] = left;
right_array[number_pair_count] = right;
left_occurences[left] += 1;
right_occurences[right] += 1;
if (left > max_left) max_left = left;
if (right > max_right) max_right = right;
number_pair_count += 1;
}
bool is_digit(c8 c)
{
return c >= '0' && c <= '9';
}
void insert_sort(i32* ptr, usize len)
{
for (usize i = 1; i < len; ++i)
{
i32 x = ptr[i];
usize j = i;
while (j > 0 && ptr[j - 1] > x) {
ptr[j] = ptr[j - 1];
j -= 1;
}
ptr[j] = x;
}
}
void println_u64(u64 value)
{
/* The longest string we produce would be "18446744073709551615\n", which is
* 21 bytes long (we don't care about the null terminator).
*/
c8 buffer[21];
usize strlen = 1;
buffer[20] = '\n';
do
{
c8 digit = (value % 10) + '0';
buffer[20 - strlen] = digit;
strlen += 1;
value /= 10;
} while (value > 0);
write(stdout, &buffer[21 - strlen], strlen);
}