This commit is contained in:
Zack Buhman 2024-12-09 02:19:22 -06:00
parent eef69e8406
commit c7febb0b23
15 changed files with 288 additions and 5 deletions

3
aoc.mk
View File

@ -5,7 +5,8 @@ OBJ = \
runner.o \ runner.o \
unparse.o \ unparse.o \
cartesian.o \ cartesian.o \
array.o array.o \
memory.o
DREAMCAST_OBJ = \ DREAMCAST_OBJ = \
runner_dreamcast.o \ runner_dreamcast.o \

1
day9/input.txt Normal file

File diff suppressed because one or more lines are too long

15
day9/input.txt.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_day9_input_txt_start __asm("_binary_day9_input_txt_start");
extern uint32_t _binary_day9_input_txt_end __asm("_binary_day9_input_txt_end");
extern uint32_t _binary_day9_input_txt_size __asm("_binary_day9_input_txt_size");
#ifdef __cplusplus
}
#endif

1
day9/sample1.txt Normal file
View File

@ -0,0 +1 @@
2333133121414131402

15
day9/sample1.txt.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_day9_sample1_txt_start __asm("_binary_day9_sample1_txt_start");
extern uint32_t _binary_day9_sample1_txt_end __asm("_binary_day9_sample1_txt_end");
extern uint32_t _binary_day9_sample1_txt_size __asm("_binary_day9_sample1_txt_size");
#ifdef __cplusplus
}
#endif

176
day9/solution.c Normal file
View File

@ -0,0 +1,176 @@
#include <stdint.h>
#include "memory.h"
#include "printf.h"
#include "parse.h"
static int disk_map_to_blocks1(const char * input, int length,
int * blocks)
{
int head = 0;
int tail = (parse_find_first_right(input, length, '\n') - input) - 1;
tail = (tail / 2) * 2; // round down to even index
int ix = 0;
int compact_file_id = -1;
int compact_file_size = 0;
while (head <= tail) {
switch (head % 2) {
case 0: // even : a file / id
{
int file_id = head / 2;
int file_size = parse_base10_digit(input[head++]);
while (file_size > 0) {
blocks[ix++] = file_id;
file_size -= 1;
}
}
break;
case 1: // odd : free space
{
int free_space = parse_base10_digit(input[head++]);
while (free_space > 0) {
if (compact_file_size == 0) { // next from tail
compact_file_id = tail / 2;
compact_file_size = parse_base10_digit(input[tail]);
tail -= 2;
}
blocks[ix++] = compact_file_id;
compact_file_size -= 1;
free_space -= 1;
}
}
break;
}
}
while (compact_file_size > 0) {
blocks[ix++] = compact_file_id;
compact_file_size -= 1;
}
return ix;
}
static int64_t calculate_checksum(int * blocks, int length)
{
int64_t sum = 0;
for (int i = 0; i < length; i++) {
int64_t id = blocks[i];
if (id < 0)
continue;
int64_t next_sum = sum + id * (int64_t)i;
if (next_sum < sum)
printf("overflow\n");
sum = next_sum;
}
return sum;
}
static int allocate_leftmost_freespace(const char * free_list,
int file_id,
int file_size)
{
for (int free_ix = 0; free_ix < file_id; free_ix += 1) {
if (free_list[free_ix] >= file_size) {
// allocate this free space to this file
return free_ix;
}
}
return -1;
}
static int disk_map_to_blocks2(const char * input, int length,
int * blocks)
{
int tail = (parse_find_first_right(input, length, '\n') - input) - 1;
tail = (tail / 2) * 2; // round down to even index
char free_list[length / 2];
for (int i = 0; i < length / 2; i++) {
free_list[i] = parse_base10_digit(input[i * 2 + 1]);
}
int alloc_ids[length / 2];
while (tail >= 0) {
int file_id = tail / 2;
int file_size = parse_base10_digit(input[tail]);
int free_ix = allocate_leftmost_freespace(free_list,
file_id,
file_size);
if (free_ix != -1) {
// move the file to the free space
free_list[free_ix] -= file_size;
alloc_ids[file_id] = free_ix * 2 + 1;
} else {
// do not move the file
alloc_ids[file_id] = file_id * 2 + 0;
}
tail -= 2;
}
/*
for (int i = 0; i < length / 2; i++) {
printf("%d %d ; ", i, alloc_ids[i]);
}
printf("\n");
*/
// build the block list from alloc_ids
int ix = 0;
for (int disk_map_ix = 0; disk_map_ix < length; disk_map_ix++) {
int map_size = parse_base10_digit(input[disk_map_ix]);
// find alloc_ids for this disk_map_ix, starting from the end of alloc_ids
for (int file_id = (length / 2) - 1; file_id >= 0; file_id -= 1) {
if (alloc_ids[file_id] == disk_map_ix) {
int file_size = parse_base10_digit(input[file_id * 2 + 0]);
for (int i = 0; i < file_size; i++) {
blocks[ix++] = file_id;
}
map_size -= file_size;
}
}
// is there free space for this disk_map_ix?
while (map_size > 0) {
blocks[ix++] = -1;
map_size -= 1;
}
}
return ix;
}
static void print_blocks(int * blocks, int length)
{
for (int i = 0; i < length; i++) {
int file_id = blocks[i];
if (file_id == -1)
print_char('.');
else
printf("%d", file_id);
}
print_char('\n');
}
int64_t day9_part1(const char * input, int length)
{
int blocks[length * 9];
int ix = disk_map_to_blocks1(input, length, blocks);
//print_blocks(blocks, ix);
return calculate_checksum(blocks, ix);
}
int64_t day9_part2(const char * input, int length)
{
int blocks[length * 9];
int ix = disk_map_to_blocks2(input, length, blocks);
//print_blocks(blocks, ix);
return calculate_checksum(blocks, ix);
}

View File

@ -15,6 +15,8 @@
#include "day7/input.txt.h" #include "day7/input.txt.h"
#include "day8/sample1.txt.h" #include "day8/sample1.txt.h"
#include "day8/input.txt.h" #include "day8/input.txt.h"
#include "day9/sample1.txt.h"
#include "day9/input.txt.h"
static struct start_size sample[][2] = { static struct start_size sample[][2] = {
{ {
@ -65,6 +67,12 @@ static struct start_size sample[][2] = {
{ ( char *)&_binary_day8_sample1_txt_start, { ( char *)&_binary_day8_sample1_txt_start,
(uint32_t)&_binary_day8_sample1_txt_size }, (uint32_t)&_binary_day8_sample1_txt_size },
}, },
{
{ ( char *)&_binary_day9_sample1_txt_start,
(uint32_t)&_binary_day9_sample1_txt_size },
{ ( char *)&_binary_day9_sample1_txt_start,
(uint32_t)&_binary_day9_sample1_txt_size },
},
}; };
static struct start_size input[] = { static struct start_size input[] = {
@ -84,4 +92,6 @@ static struct start_size input[] = {
(uint32_t)&_binary_day7_input_txt_size }, (uint32_t)&_binary_day7_input_txt_size },
{ ( char *)&_binary_day8_input_txt_start, { ( char *)&_binary_day8_input_txt_start,
(uint32_t)&_binary_day8_input_txt_size }, (uint32_t)&_binary_day8_input_txt_size },
{ ( char *)&_binary_day9_input_txt_start,
(uint32_t)&_binary_day9_input_txt_size },
}; };

17
memory.c Normal file
View File

@ -0,0 +1,17 @@
#include <stdint.h>
#include "memory.h"
void memory_set_char(char * buf, char c, int size)
{
for (int i = 0; i < size; i += 1) {
buf[i] = c;
}
}
void memory_set_int(int * buf, int c, int size)
{
for (int i = 0; i < size; i += 1) {
buf[i] = c;
}
}

12
memory.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void memory_set_char(char * buf, char c, int size);
void memory_set_int(int * buf, int c, int size);
#ifdef __cplusplus
}
#endif

17
parse.c
View File

@ -11,7 +11,18 @@ const char * parse_skip(const char * s, char c)
return s; return s;
} }
static int base10_digit(char c) const char * parse_find_first_right(const char * s, int length, char c)
{
const char * ss = &s[length - 1];
while (ss >= s) {
if (*ss == c)
return ss;
ss--;
}
return s;
}
int parse_base10_digit(char c)
{ {
switch (c) { switch (c) {
case '0': return 0; case '0': return 0;
@ -33,7 +44,7 @@ const char * parse_base10(const char * s, int * n)
*n = 0; *n = 0;
while (true) { while (true) {
int digit = base10_digit(*s); int digit = parse_base10_digit(*s);
if (digit == -1) if (digit == -1)
break; break;
@ -50,7 +61,7 @@ const char * parse_base10_64(const char * s, int64_t * n)
*n = 0; *n = 0;
while (true) { while (true) {
int digit = base10_digit(*s); int digit = parse_base10_digit(*s);
if (digit == -1) if (digit == -1)
break; break;

View File

@ -7,6 +7,8 @@ extern "C" {
#endif #endif
const char * parse_skip(const char * s, char c); const char * parse_skip(const char * s, char c);
const char * parse_find_first_right(const char * s, int length, char c);
int parse_base10_digit(char c);
const char * parse_base10(const char * s, int * n); const char * parse_base10(const char * s, int * n);
const char * parse_base10_64(const char * s, int64_t * n); const char * parse_base10_64(const char * s, int64_t * n);
const char * parse_match(const char * s, const char * m); const char * parse_match(const char * s, const char * m);

View File

@ -32,6 +32,9 @@ bool runner_tick(struct runner_state * runner_state)
int part = tick % 2; int part = tick % 2;
int day = tick / 2; int day = tick / 2;
if (day < 8)
return true;
runner_state->want_render = solution[day].render != NULL; runner_state->want_render = solution[day].render != NULL;
char * buf; char * buf;

View File

@ -17,6 +17,8 @@ int64_t day7_part1(const char * input, int length);
int64_t day7_part2(const char * input, int length); int64_t day7_part2(const char * input, int length);
int64_t day8_part1(const char * input, int length); int64_t day8_part1(const char * input, int length);
int64_t day8_part2(const char * input, int length); int64_t day8_part2(const char * input, int length);
int64_t day9_part1(const char * input, int length);
int64_t day9_part2(const char * input, int length);
struct day_funcs solution[] = { struct day_funcs solution[] = {
{ {
@ -51,4 +53,8 @@ struct day_funcs solution[] = {
{day8_part1, day8_part2}, {day8_part1, day8_part2},
NULL, NULL,
}, },
{
{day9_part1, day9_part2},
NULL,
},
}; };

View File

@ -433,6 +433,7 @@ int main()
uint32_t done_frame = 0; uint32_t done_frame = 0;
bool done = false; bool done = false;
//int last_state = -1;
while (true) { while (true) {
if (!done && runner_tick(&runner_state)) { if (!done && runner_tick(&runner_state)) {
done = true; done = true;
@ -440,9 +441,18 @@ int main()
} }
if (done && (frame == done_frame + 3)) if (done && (frame == done_frame + 3))
break; break;
/*
if (runner_state.tick != last_state) {
last_state = runner_state.tick;
serial::integer<uint32_t>(runner_state.tick);
}
*/
} }
serial::string("return\n"); serial::string("return\n");
serial::string("return\n");
serial::string("return\n");
serial::string("return\n");
} }

View File

@ -24,4 +24,7 @@ DAY_OBJ = \
day7/solution.o \ day7/solution.o \
day8/sample1.txt.o \ day8/sample1.txt.o \
day8/input.txt.o \ day8/input.txt.o \
day8/solution.o day8/solution.o \
day9/sample1.txt.o \
day9/input.txt.o \
day9/solution.o