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(®, regex, REG_EXTENDED)) { 95 puts("Failed to compile regex"); 96 return NULL; 97 } 98 99 if (regexec(®, passLine, maxGroups, matches, 0)) { 100 puts("Failed to find match"); 101 return NULL; 102 } 103 regfree(®); 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 }