Day 1
This commit is contained in:
200
src/01.c
Normal file
200
src/01.c
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user