#include #include #include #include #if 0 #define PART_1 #else #define PART_2 #endif #if 0 #define FILE_PATH "example-valid.txt" #else #define FILE_PATH "input.txt" #endif char fields[8][4] = {"byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid", "cid"}; size_t valid = 0; void parse() { FILE *fp = fopen(FILE_PATH, "r"); if(!fp) { fprintf(stderr, "ERROR: Could not open file: %s", FILE_PATH); exit(EXIT_FAILURE); } char line[2048] = {0}; int field_valid[8] = {0}; while(fgets(line, sizeof(line), fp) != NULL) { if(line[0] == '\n' || strncmp(line, "EOF", 3) == 0) { int result = 1; for(int i = 0; i < 7; i++) result *= field_valid[i]; valid += result; memset(field_valid, 0 , sizeof(field_valid)); continue; } char *tok = strtok(line, " "); while(tok != NULL) { for(int i = 0; i < 8; i++) { if(strncmp(tok, fields[i], 3) == 0) { #ifdef PART_1 field_valid[i] = 1; #endif #ifdef PART_2 char *saveptr; (void)strtok_r(tok, ":", &saveptr); char *val = strtok_r(NULL, ":", &saveptr); assert(val != NULL); assert(strtok_r(NULL, ":", &saveptr) == NULL); if(val[strlen(val)-1] == '\n') val[strlen(val)-1] = '\0'; int ival; switch(i) { case 0: ival = atoi(val); if(ival >= 1920 && ival <= 2002) field_valid[i] = 1; break; case 1: ival = atoi(val); if(ival >= 2010 && ival <= 2020) field_valid[i] = 1; break; case 2: ival = atoi(val); if(ival >= 2020 && ival <= 2030) field_valid[i] = 1; break; case 3: if(strlen(val) == 5) { if(!(val[3] == 'c' && val[4] == 'm')) break; char _val[4] = {0}; _val[0] = val[0]; _val[1] = val[1]; _val[2] = val[2]; ival = atoi(_val); if(ival >= 150 && ival <= 193) field_valid[i] = 1; } if(strlen(val) == 4) { if(!(val[2] == 'i' && val[3] == 'n')) break; char _val[3] = {0}; _val[0] = val[0]; _val[1] = val[1]; ival = atoi(_val); if(ival >= 59 && ival <= 76) field_valid[i] = 1; } break; case 4: int num = 0; char valid_vals[16] = "0123456789abcdef"; for(int k = 1; k <= strlen(val); k++) for(int j = 0; j < 16; j++) if(val[k] == valid_vals[j]) num++; if(val[0] == '#' && num == 6) field_valid[i] = 1; break; case 5: int valid_ecl = 0; char valid_cols[7][4] = {"amb", "blu", "brn", "gry", "grn", "hzl", "oth"}; for(int k = 0; k < 7; k++) if(strncmp(val, valid_cols[k], 3) == 0) valid_ecl++; if(valid_ecl == 1) field_valid[i] = 1; break; case 6: int valid_pid = 0; if(strlen(val) != 9) break; char valid_nums[10] = "0123456789"; for(int k = 0; k < strlen(val); k++) for(int j = 0; j < 10; j++) if(val[k] == valid_nums[j]) valid_pid++; if(valid_pid == 9) field_valid[i] = 1; break; } #endif } } tok = strtok(NULL, " "); } } fclose(fp); } int main(void) { parse(); printf("%ld passports are valid\n", valid); return 0; }