216 lines
4.9 KiB
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(®ex, pattern, REG_EXTENDED))
|
||
|
{
|
||
|
fprintf(stderr, "error compiling regex");
|
||
|
return -1;
|
||
|
}
|
||
|
int rc = regexec(®ex, line, 2, pmatch, 0);
|
||
|
if (rc)
|
||
|
{
|
||
|
char buf[2048];
|
||
|
regerror(rc, ®ex, 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(®ex, pattern, REG_EXTENDED))
|
||
|
{
|
||
|
fprintf(stderr, "error compiling regex");
|
||
|
return NULL;
|
||
|
}
|
||
|
for (int i = 0; ; i++)
|
||
|
{
|
||
|
if (regexec(®ex, 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(®ex);
|
||
|
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(®ex, pattern, REG_EXTENDED))
|
||
|
{
|
||
|
fprintf(stderr, "error compiling regex");
|
||
|
return NULL;
|
||
|
}
|
||
|
for (int i = 0; ; i++)
|
||
|
{
|
||
|
if (regexec(®ex, 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(®ex, 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(®ex, s, 4, pmatch, 0))
|
||
|
break;
|
||
|
cur->next = parse_play(line, pmatch[0].rm_eo);
|
||
|
cur = cur->next;
|
||
|
s += pmatch[0].rm_eo;
|
||
|
}
|
||
|
regfree(®ex);
|
||
|
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;
|
||
|
}
|