day9
This commit is contained in:
parent
eef69e8406
commit
c7febb0b23
3
aoc.mk
3
aoc.mk
@ -5,7 +5,8 @@ OBJ = \
|
||||
runner.o \
|
||||
unparse.o \
|
||||
cartesian.o \
|
||||
array.o
|
||||
array.o \
|
||||
memory.o
|
||||
|
||||
DREAMCAST_OBJ = \
|
||||
runner_dreamcast.o \
|
||||
|
1
day9/input.txt
Normal file
1
day9/input.txt
Normal file
File diff suppressed because one or more lines are too long
15
day9/input.txt.h
Normal file
15
day9/input.txt.h
Normal 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
1
day9/sample1.txt
Normal file
@ -0,0 +1 @@
|
||||
2333133121414131402
|
15
day9/sample1.txt.h
Normal file
15
day9/sample1.txt.h
Normal 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
176
day9/solution.c
Normal 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);
|
||||
}
|
@ -15,6 +15,8 @@
|
||||
#include "day7/input.txt.h"
|
||||
#include "day8/sample1.txt.h"
|
||||
#include "day8/input.txt.h"
|
||||
#include "day9/sample1.txt.h"
|
||||
#include "day9/input.txt.h"
|
||||
|
||||
static struct start_size sample[][2] = {
|
||||
{
|
||||
@ -65,6 +67,12 @@ static struct start_size sample[][2] = {
|
||||
{ ( char *)&_binary_day8_sample1_txt_start,
|
||||
(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[] = {
|
||||
@ -84,4 +92,6 @@ static struct start_size input[] = {
|
||||
(uint32_t)&_binary_day7_input_txt_size },
|
||||
{ ( char *)&_binary_day8_input_txt_start,
|
||||
(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
17
memory.c
Normal 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
12
memory.h
Normal 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
17
parse.c
@ -11,7 +11,18 @@ const char * parse_skip(const char * s, char c)
|
||||
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) {
|
||||
case '0': return 0;
|
||||
@ -33,7 +44,7 @@ const char * parse_base10(const char * s, int * n)
|
||||
*n = 0;
|
||||
|
||||
while (true) {
|
||||
int digit = base10_digit(*s);
|
||||
int digit = parse_base10_digit(*s);
|
||||
if (digit == -1)
|
||||
break;
|
||||
|
||||
@ -50,7 +61,7 @@ const char * parse_base10_64(const char * s, int64_t * n)
|
||||
*n = 0;
|
||||
|
||||
while (true) {
|
||||
int digit = base10_digit(*s);
|
||||
int digit = parse_base10_digit(*s);
|
||||
if (digit == -1)
|
||||
break;
|
||||
|
||||
|
2
parse.h
2
parse.h
@ -7,6 +7,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
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_64(const char * s, int64_t * n);
|
||||
const char * parse_match(const char * s, const char * m);
|
||||
|
3
runner.c
3
runner.c
@ -32,6 +32,9 @@ bool runner_tick(struct runner_state * runner_state)
|
||||
int part = tick % 2;
|
||||
int day = tick / 2;
|
||||
|
||||
if (day < 8)
|
||||
return true;
|
||||
|
||||
runner_state->want_render = solution[day].render != NULL;
|
||||
|
||||
char * buf;
|
||||
|
@ -17,6 +17,8 @@ int64_t day7_part1(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_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[] = {
|
||||
{
|
||||
@ -51,4 +53,8 @@ struct day_funcs solution[] = {
|
||||
{day8_part1, day8_part2},
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
{day9_part1, day9_part2},
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
@ -433,6 +433,7 @@ int main()
|
||||
|
||||
uint32_t done_frame = 0;
|
||||
bool done = false;
|
||||
//int last_state = -1;
|
||||
while (true) {
|
||||
if (!done && runner_tick(&runner_state)) {
|
||||
done = true;
|
||||
@ -440,9 +441,18 @@ int main()
|
||||
}
|
||||
if (done && (frame == done_frame + 3))
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,4 +24,7 @@ DAY_OBJ = \
|
||||
day7/solution.o \
|
||||
day8/sample1.txt.o \
|
||||
day8/input.txt.o \
|
||||
day8/solution.o
|
||||
day8/solution.o \
|
||||
day9/sample1.txt.o \
|
||||
day9/input.txt.o \
|
||||
day9/solution.o
|
||||
|
Loading…
x
Reference in New Issue
Block a user