Add solutions for day 9, task 1
This commit is contained in:
parent
c93d336e90
commit
49d88e6913
4 changed files with 2231 additions and 0 deletions
3
day_9/Makefile
Normal file
3
day_9/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
TARGET := day_9
|
||||||
|
|
||||||
|
include ../Makefile.common.mk
|
2000
day_9/input.txt
Normal file
2000
day_9/input.txt
Normal file
File diff suppressed because it is too large
Load diff
56
day_9/lexer.l
Normal file
56
day_9/lexer.l
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%option warn nodefault
|
||||||
|
|
||||||
|
/* makes the scanner terminate after reaching <<EOF>> instead of assuming a new input was provided */
|
||||||
|
%option noyywrap
|
||||||
|
/* disable some unused functionality, add scanner tracking */
|
||||||
|
%option nounput noinput batch debug
|
||||||
|
|
||||||
|
/* gimme a reentrant parser (overkill but more pure) */
|
||||||
|
%option reentrant
|
||||||
|
|
||||||
|
%option bison-bridge
|
||||||
|
|
||||||
|
|
||||||
|
NL [\n]
|
||||||
|
SPACE " "
|
||||||
|
|
||||||
|
DOWN "D"
|
||||||
|
UP "U"
|
||||||
|
LEFT "L"
|
||||||
|
RIGHT "R"
|
||||||
|
|
||||||
|
/*general definitions*/
|
||||||
|
NUM [0-9]
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
{NL} { return NEWLINE; }
|
||||||
|
{SPACE} { /* return SPACE; */ }
|
||||||
|
{DOWN} { return DOWN; }
|
||||||
|
{UP} { return UP; }
|
||||||
|
{LEFT} { return LEFT; }
|
||||||
|
{RIGHT} { return RIGHT; }
|
||||||
|
|
||||||
|
{NUM}+ {
|
||||||
|
unsigned long num = strtoul(yytext, NULL, 10);
|
||||||
|
yylval->num = num;
|
||||||
|
return NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
<<EOF>> {
|
||||||
|
return END_OF_FILE;
|
||||||
|
}
|
||||||
|
. {
|
||||||
|
printf("[error] Encountered unexpected token %s\n", yytext);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
%%
|
172
day_9/parser.y
Normal file
172
day_9/parser.y
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/* Require bison minimal version */
|
||||||
|
%require "3.2"
|
||||||
|
|
||||||
|
/* write out a header file containing the token defines */
|
||||||
|
%header
|
||||||
|
|
||||||
|
// Code for the header file generated by bison
|
||||||
|
%code requires {
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MAX_X 500
|
||||||
|
#define MAX_Y 500
|
||||||
|
|
||||||
|
typedef void* yyscan_t;
|
||||||
|
|
||||||
|
struct parser_state {
|
||||||
|
bool field[MAX_X][MAX_Y];
|
||||||
|
|
||||||
|
size_t head_x;
|
||||||
|
size_t head_y;
|
||||||
|
size_t tail_x;
|
||||||
|
size_t tail_y;
|
||||||
|
|
||||||
|
unsigned long visited;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code for the c file
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "parser.h"
|
||||||
|
#include "lexer.h"
|
||||||
|
|
||||||
|
void yyerror(struct parser_state* state, yyscan_t scanner, const char* msg) {
|
||||||
|
(void)state;
|
||||||
|
(void)scanner;
|
||||||
|
fprintf(stderr, "\033[93mSyntax Error: %s\033[0m\n", msg);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
// define a reentrant parser
|
||||||
|
%define api.pure
|
||||||
|
|
||||||
|
// enable parser tracing and detailed error messages (plus Lookahead Correction)
|
||||||
|
%define parse.trace
|
||||||
|
%define parse.error detailed
|
||||||
|
%define parse.lac full
|
||||||
|
|
||||||
|
%lex-param { yyscan_t scanner }
|
||||||
|
%parse-param { struct parser_state* state }
|
||||||
|
%parse-param { yyscan_t scanner }
|
||||||
|
|
||||||
|
%union {
|
||||||
|
unsigned long num;
|
||||||
|
}
|
||||||
|
|
||||||
|
%start input
|
||||||
|
%token NEWLINE
|
||||||
|
%token DOWN UP LEFT RIGHT
|
||||||
|
%token <num> NUM
|
||||||
|
%term END_OF_FILE
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
input
|
||||||
|
: line input
|
||||||
|
| END_OF_FILE { return 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
line
|
||||||
|
: movement NEWLINE
|
||||||
|
| NEWLINE
|
||||||
|
;
|
||||||
|
|
||||||
|
movement
|
||||||
|
: UP NUM {
|
||||||
|
for (size_t i = 0; i < $2; i++) {
|
||||||
|
state->head_y++;
|
||||||
|
if ((state->head_y - state->tail_y) > 1) {
|
||||||
|
state->tail_y = state->head_y - 1;
|
||||||
|
state->tail_x = state->head_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state->field[state->tail_x][state->tail_y]) {
|
||||||
|
state->field[state->tail_x][state->tail_y] = true;
|
||||||
|
state->visited++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| DOWN NUM {
|
||||||
|
for (size_t i = 0; i < $2; i++) {
|
||||||
|
state->head_y--;
|
||||||
|
if ((state->tail_y - state->head_y) > 1) {
|
||||||
|
state->tail_y = state->head_y + 1;
|
||||||
|
state->tail_x = state->head_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state->field[state->tail_x][state->tail_y]) {
|
||||||
|
state->field[state->tail_x][state->tail_y] = true;
|
||||||
|
state->visited++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| RIGHT NUM {
|
||||||
|
for (size_t i = 0; i < $2; i++) {
|
||||||
|
state->head_x++;
|
||||||
|
if ((state->head_x - state->tail_x) > 1) {
|
||||||
|
state->tail_x = state->head_x - 1;
|
||||||
|
state->tail_y = state->head_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state->field[state->tail_x][state->tail_y]) {
|
||||||
|
state->field[state->tail_x][state->tail_y] = true;
|
||||||
|
state->visited++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| LEFT NUM {
|
||||||
|
for (size_t i = 0; i < $2; i++) {
|
||||||
|
state->head_x--;
|
||||||
|
if ((state->tail_x - state->head_x) > 1) {
|
||||||
|
state->tail_x = state->head_x + 1;
|
||||||
|
state->tail_y = state->head_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state->field[state->tail_x][state->tail_y]) {
|
||||||
|
state->field[state->tail_x][state->tail_y] = true;
|
||||||
|
state->visited++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct parser_state *state = calloc(1, sizeof(struct parser_state));
|
||||||
|
if (!state) {
|
||||||
|
fprintf(stderr, "\033[91m[error] Ran out of memory\033[0m\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->head_x = MAX_X / 2;
|
||||||
|
state->head_y = MAX_Y / 2;
|
||||||
|
state->tail_x = MAX_X / 2;
|
||||||
|
state->tail_y = MAX_Y / 2;
|
||||||
|
|
||||||
|
state->visited = 1; // the starting position
|
||||||
|
state->field[state->tail_x][state->tail_y] = true;
|
||||||
|
|
||||||
|
yyscan_t scanner;
|
||||||
|
if (yylex_init(&scanner)) {
|
||||||
|
fprintf(stderr, "\033[91m[error] Could not initialize lexer\033[0m\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yyparse(state, scanner)) {
|
||||||
|
// TODO: Error handling https://www.gnu.org/software/bison/manual/html_node/Parser-Function.html
|
||||||
|
// error during parse occured
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
yylex_destroy(scanner);
|
||||||
|
|
||||||
|
// task 1
|
||||||
|
printf("Visited nodes: %zu\n", state->visited);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue