advent2023

Advent of Code 2023 solutions
git clone git://bsandro.tech/advent2023
Log | Files | Refs | LICENSE

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 }