Add solutions for day 9, task 1

This commit is contained in:
Felix Suchert 2023-01-15 12:00:18 +01:00
parent c93d336e90
commit 49d88e6913
Signed by: feliix42
GPG key ID: 24363525EA0E8A99
4 changed files with 2231 additions and 0 deletions

3
day_9/Makefile Normal file
View file

@ -0,0 +1,3 @@
TARGET := day_9
include ../Makefile.common.mk

2000
day_9/input.txt Normal file

File diff suppressed because it is too large Load diff

56
day_9/lexer.l Normal file
View 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
View 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;
}