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