puzzle.c (2150B)
1 #define _DEFAULT_SOURCE 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <errno.h> 6 #include <string.h> 7 #include <strings.h> 8 #include <assert.h> 9 #include <stdbool.h> 10 11 #define STR_LEN 1024 12 13 int get_digits_p1(const char *); 14 int get_digits_p2(const char *); 15 int pop_digit(const char *); 16 17 bool is_digit(char b) { 18 return b>='0' && b<='9'; 19 } 20 21 bool is_letter(char b) { 22 return b>='a' && b<='z'; 23 } 24 25 static const char* digits[9] = { 26 "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" 27 }; 28 29 void puzzle(const char *filename, long long *result1, long long *result2) { 30 FILE *infile = fopen(filename, "r"); 31 if (infile == NULL) { 32 fprintf(stderr, "fopen() error: %s\n", strerror(errno)); 33 return; 34 } 35 36 char buf[STR_LEN] = {0}; 37 unsigned int line_num = 0; 38 39 *result1 = 0; 40 *result2 = 0; 41 42 while (fgets(buf, STR_LEN, infile) != NULL) { 43 int num1 = get_digits_p1(buf); 44 int num2 = get_digits_p2(buf); 45 *result1 += num1; 46 *result2 += num2; 47 ++line_num; 48 bzero(buf, STR_LEN); 49 } 50 51 // mutiny! ignoring feof/ferror. 52 fclose(infile); 53 54 (void)result2; 55 (void)digits; 56 } 57 58 int get_digits_p1(const char *str) { 59 int len = strlen(str); 60 int n1 = -1, n2 = -1; 61 for (int i=0; i<len; ++i) { 62 char b = str[i]; 63 if (is_digit(b)) { 64 n2 = b-'0'; 65 if (n1==-1) n1=b-'0'; 66 } 67 } 68 return n1*10+n2; 69 } 70 71 int get_digits_p2(const char *str) { 72 (void)str; 73 74 int len = strlen(str); 75 int n1=-1, n2=-1, i=0; 76 (void)n2; 77 while (i<len) { 78 char b = str[i]; 79 if (is_digit(b)) { 80 n2 = b-'0'; 81 if (n1==-1) n1=b-'0'; 82 ++i; 83 } else if (is_letter(b)) { 84 int di = pop_digit(str+i); 85 if (di==-1) { 86 ++i; 87 } else { 88 n2=di+1; 89 if (n1==-1) n1=n2; 90 //printf("(%d) found digit %d (%s) (len %d of %d) in %s (full %s)\n", i, di+1, digits[di], d_len, len, str+i, str); 91 92 // initial screwup, test was working but real data did not because of overlaps:) 93 //i+=d_len; 94 ++i; 95 } 96 } else { 97 ++i; 98 } 99 } 100 101 return n1*10+n2; 102 } 103 104 int pop_digit(const char *str) { 105 int len2 = strlen(str); 106 for (int i=0; i<9; ++i) { 107 int len1 = strlen(digits[i]); 108 if (len2<len1) continue; 109 if (strncmp(digits[i], str, len1) == 0) { 110 return i; 111 } 112 } 113 return -1; 114 }