Day 2 part I
This commit is contained in:
parent
b6c66136f7
commit
941ee5f329
4
Makefile
4
Makefile
@ -14,5 +14,9 @@ bin/%: src/%.c $(STDLIB_SOURCES) $(STDLIB_HEADERS)
|
|||||||
gcc $(CFLAGS) $< $(STDLIB_SOURCES) -o $@
|
gcc $(CFLAGS) $< $(STDLIB_SOURCES) -o $@
|
||||||
strip -R .comment $@
|
strip -R .comment $@
|
||||||
|
|
||||||
|
out/%.txt: in/%.txt bin/%
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
<$< bin/$* >$@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf bin
|
rm -rf bin
|
||||||
|
@ -14,3 +14,7 @@ Run `make` to build everything.
|
|||||||
## Running
|
## Running
|
||||||
|
|
||||||
Every program accepts the input through `stdin` and outputs through `stdout`.
|
Every program accepts the input through `stdin` and outputs through `stdout`.
|
||||||
|
|
||||||
|
If you place puzzle inputs in files at `in/01.txt`, `in/02.txt`, etc., then you
|
||||||
|
can use make to compile and compute the answer by running `make out/01.txt`,
|
||||||
|
`make out/02.txt`, etc.
|
||||||
|
121
src/02.c
Normal file
121
src/02.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include <common.h>
|
||||||
|
#include <buffer.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 4096UL
|
||||||
|
|
||||||
|
typedef enum parser_state {
|
||||||
|
parser_state_digits_start,
|
||||||
|
parser_state_digits_rest,
|
||||||
|
parser_state_whitespace,
|
||||||
|
} parser_state;
|
||||||
|
|
||||||
|
typedef struct parser {
|
||||||
|
i8 prev;
|
||||||
|
i8 current;
|
||||||
|
i8 diff;
|
||||||
|
bool unsafe;
|
||||||
|
parser_state state;
|
||||||
|
} parser;
|
||||||
|
|
||||||
|
void parser_process(parser* parser, const c8* ptr, usize len);
|
||||||
|
bool is_digit(c8 c);
|
||||||
|
void println_u64(u64 value);
|
||||||
|
|
||||||
|
u64 safe_count = 0;
|
||||||
|
|
||||||
|
i32 main(i32 argc, char *argv[])
|
||||||
|
{
|
||||||
|
c8* buffer = buffer_init(BUFFER_SIZE);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
println_u64(safe_count);
|
||||||
|
|
||||||
|
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_digits_start:
|
||||||
|
if (is_digit(c)) {
|
||||||
|
parser->prev = parser->prev * 10 + (c - '0');
|
||||||
|
ptr += 1;
|
||||||
|
} else {
|
||||||
|
parser->state = parser_state_whitespace;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case parser_state_digits_rest:
|
||||||
|
if (is_digit(c)) {
|
||||||
|
parser->current = parser->current * 10 + (c - '0');
|
||||||
|
ptr += 1;
|
||||||
|
} else {
|
||||||
|
i8 diff = parser->current - parser->prev;
|
||||||
|
if (diff * parser->diff < 0 || diff < -3 || diff == 0 || diff > 3) {
|
||||||
|
parser->unsafe = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser->prev = parser->current;
|
||||||
|
parser->current = 0;
|
||||||
|
parser->diff = diff;
|
||||||
|
parser->state = parser_state_whitespace;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case parser_state_whitespace:
|
||||||
|
if (c == '\n') {
|
||||||
|
if (!parser->unsafe) {
|
||||||
|
safe_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser->prev = 0;
|
||||||
|
parser->current = 0;
|
||||||
|
parser->diff = 0;
|
||||||
|
parser->unsafe = false;
|
||||||
|
parser->state = parser_state_digits_start;
|
||||||
|
|
||||||
|
ptr += 1;
|
||||||
|
} else if (is_digit(c)) {
|
||||||
|
parser->state = parser_state_digits_rest;
|
||||||
|
} else {
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_digit(c8 c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user