advent-of-code-2023/day2/part1.c

216 lines
4.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <regex.h>
#include <string.h>
typedef struct elfgame {
long number;
struct elfgame_play *plays;
struct elfgame *next;
} elfgame;
typedef struct elfgame_play {
long red, blue, green;
struct elfgame_play *next;
} elfgame_play;
elfgame *first_game;
void read_line(char* linebuf, FILE* file)
{
char* str = fgets(linebuf, 2048, file);
if (feof(file))
{
return;
}
if (str == NULL)
{
fprintf(stderr, "Fgets error");
linebuf[0] = '\0';
}
}
long get_gamenum(char* line)
{
regex_t regex;
char pattern[] = "Game ([0-9]+):.*";
regmatch_t pmatch[2];
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return -1;
}
int rc = regexec(&regex, line, 2, pmatch, 0);
if (rc)
{
char buf[2048];
regerror(rc, &regex, buf, 2048);
fprintf(stderr, "error execing regex");
return -1;
}
return strtoul(line + pmatch[1].rm_so, NULL, 10);
}
elfgame_play *parse_play(char *line, int offset)
{
regex_t regex;
regmatch_t pmatch[3];
char pattern[] = "([0-9]+)[[:space:]](red|green|blue);?";
char *s = line;
elfgame_play *p = malloc(sizeof(elfgame_play));
if (p == NULL)
{
fprintf(stderr, "OOM");
return NULL;
}
p->red = p->blue = p->green = 0;
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return NULL;
}
for (int i = 0; ; i++)
{
if (regexec(&regex, s, 3, pmatch, 0))
break;
if (s >= line + offset)
break;
long count = strtoul(s + pmatch[1].rm_so, NULL, 10);
if (strncmp(s + pmatch[2].rm_so, "red", 3) == 0)
{
p->red += count;
}
if (strncmp(s + pmatch[2].rm_so, "blue", 4) == 0)
{
p->blue += count;
}
if (strncmp(s + pmatch[2].rm_so, "green", 5) == 0)
{
p->green += count;
}
s += pmatch[0].rm_eo;
}
regfree(&regex);
return p;
}
elfgame_play *parse_plays(char* line, int offset)
{
regex_t regex;
regmatch_t pmatch[3];
char pattern[] = "([0-9]+)[[:space:]](red|blue|green)";
char *s = line;
elfgame_play *first = malloc(sizeof(elfgame_play));
if (first == NULL)
{
fprintf(stderr, "OOM");
return NULL;
}
elfgame_play *cur = first;
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return NULL;
}
for (int i = 0; ; i++)
{
if (regexec(&regex, s, 3, pmatch, 0))
break;
if (s > line + offset)
break;
elfgame_play *p = malloc(sizeof(elfgame_play));
if (p == NULL)
{
fprintf(stderr, "OOM");
return NULL;
}
p->red = p->blue = p->green = 0;
long count = strtoul(s + pmatch[1].rm_so, NULL, 10);
if (strncmp(s + pmatch[2].rm_so, "red", 3) == 0)
{
p->red += count;
}
if (strncmp(s + pmatch[2].rm_so, "blue", 4) == 0)
{
p->blue += count;
}
if (strncmp(s + pmatch[2].rm_so, "green", 5) == 0)
{
p->green += count;
}
cur->next = p;
cur = cur->next;
s += pmatch[0].rm_eo;
}
return first;
}
elfgame *parse_game(char* line)
{
regex_t regex;
regmatch_t pmatch[4];
char pattern[] = "(([0-9]+)[[:space:]](red|blue|green),?[[:space:]]?)+;?";
if (regcomp(&regex, pattern, REG_EXTENDED))
{
fprintf(stderr, "error compiling regex");
return NULL;
}
char *s = line;
elfgame *g = malloc(sizeof(elfgame));
if (g == NULL)
{
return NULL;
}
g->number = get_gamenum(line);
elfgame_play *dummy = malloc(sizeof(elfgame_play));
if (dummy == NULL)
{
return NULL;
}
dummy->red = dummy->green = dummy->blue = 0;
elfgame_play *cur = dummy;
g->plays = dummy;
for (int i = 0; ; i++)
{
if(regexec(&regex, s, 4, pmatch, 0))
break;
cur->next = parse_play(line, pmatch[0].rm_eo);
cur = cur->next;
s += pmatch[0].rm_eo;
}
regfree(&regex);
return g;
}
int main(int argc, char *argv[])
{
char buffer[2048];
FILE* input = fopen("input", "r");
if (input == NULL)
{
fprintf(stderr, "error opening file");
return EXIT_FAILURE;
}
long sum = 0;
first_game = malloc(sizeof(elfgame));
if (first_game == NULL)
{
fprintf(stderr, "OOM");
return EXIT_FAILURE;
}
elfgame *cur = first_game;
while(true)
{
read_line(buffer, input);
if (feof(input))
break;
elfgame *g = parse_game(buffer);
cur->next = g;
cur = cur->next;
}
printf("%ld", sum);
return EXIT_SUCCESS;
}