#include #include #include #include #include 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; }