github.com/cycloss/advent-of-code@v0.0.0-20221210145555-15039b95faa6/2020/day2/day2.c (about)

     1  #include <regex.h>
     2  #include <stdbool.h>
     3  #include <stdio.h>
     4  #include <stdlib.h>
     5  #include <string.h>
     6  
     7  #define INPUT_FILE_2 "inputFiles/day2.txt"
     8  #define BUFFER_MAX 100
     9  
    10  typedef struct {
    11      int min, max;
    12      char keyChar, *pass;
    13  } cleanPassLine;
    14  
    15  bool testPasswordOne(char* password);
    16  bool testPasswordTwo(char* password);
    17  cleanPassLine* generateCpl(char* passLine);
    18  char* getMatch(int index, regmatch_t* matches, char* passLine);
    19  void runTest();
    20  
    21  int main() {
    22      puts("Part one:");
    23      runTest(testPasswordOne);
    24      puts("\nPart two:");
    25      runTest(testPasswordTwo);
    26  }
    27  
    28  void runTest(bool (*testPassword)(char*)) {
    29  
    30      FILE* inputFile = fopen(INPUT_FILE_2, "r");
    31  
    32      int okPasswords = 0;
    33  
    34      for (char buffer[BUFFER_MAX]; fgets(buffer, BUFFER_MAX, inputFile);) {
    35          if (testPassword(buffer)) {
    36              okPasswords++;
    37          }
    38      }
    39      printf("Ok passwords: %d\n", okPasswords);
    40  
    41      fclose(inputFile);
    42  }
    43  
    44  bool testPasswordOne(char* passwordLine) {
    45      cleanPassLine* cpl = generateCpl(passwordLine);
    46      if (!cpl) {
    47          printf("Failed to parse line: %s", passwordLine);
    48          exit(1);
    49      }
    50  
    51      int keyCharCount = 0;
    52      char* copyp = cpl->pass;
    53      for (char c = *copyp; c; c = *++copyp) {
    54          if (c == cpl->keyChar) {
    55              keyCharCount++;
    56          }
    57      }
    58  
    59      bool ok = keyCharCount <= cpl->max && keyCharCount >= cpl->min;
    60      free(cpl->pass);
    61      free(cpl);
    62      return ok;
    63  }
    64  
    65  bool testPasswordTwo(char* passwordLine) {
    66      cleanPassLine* cpl = generateCpl(passwordLine);
    67      if (!cpl) {
    68          printf("Failed to parse line: %s", passwordLine);
    69          exit(1);
    70      }
    71  
    72      int correctPos = 0;
    73  
    74      char* copyP = cpl->pass - 1;
    75      if (*(copyP + cpl->min) == cpl->keyChar) {
    76          correctPos++;
    77      }
    78      if (*(copyP + cpl->max) == cpl->keyChar) {
    79          correctPos++;
    80      }
    81  
    82      free(cpl->pass);
    83      free(cpl);
    84      return correctPos == 1;
    85  }
    86  
    87  cleanPassLine* generateCpl(char* passLine) {
    88      char* regex = "([0-9]+)-([0-9]+) ([a-z]): ([a-z]+)";
    89      size_t maxGroups = 5;
    90  
    91      regex_t reg;
    92      regmatch_t matches[maxGroups];
    93  
    94      if (regcomp(&reg, regex, REG_EXTENDED)) {
    95          puts("Failed to compile regex");
    96          return NULL;
    97      }
    98  
    99      if (regexec(&reg, passLine, maxGroups, matches, 0)) {
   100          puts("Failed to find match");
   101          return NULL;
   102      }
   103      regfree(&reg);
   104  
   105      char* min = getMatch(1, matches, passLine);
   106      int minNum = atoi(min);
   107      free(min);
   108  
   109      char* max = getMatch(2, matches, passLine);
   110      int maxNum = atoi(max);
   111      free(max);
   112  
   113      char* keyCharP = getMatch(3, matches, passLine);
   114      char keyChar = *keyCharP;
   115      free(keyCharP);
   116  
   117      char* passP = getMatch(4, matches, passLine);
   118  
   119      cleanPassLine* cpl = malloc(sizeof(cleanPassLine));
   120      *cpl = (cleanPassLine) { minNum, maxNum, keyChar, passP };
   121      return cpl;
   122  }
   123  
   124  char* getMatch(int index, regmatch_t* matches, char* passLine) {
   125      char* cpy = malloc(sizeof(char) * (strlen(passLine) + 1));
   126      strcpy(cpy, passLine);
   127      cpy[matches[index].rm_eo] = '\0';
   128      sprintf(cpy, "%s", cpy + matches[index].rm_so);
   129      return cpy;
   130  }