advent2021

Advent of Code 2021 Solutions
git clone git://bsandro.tech/advent2021
Log | Files | Refs | README | LICENSE

puzzle.c (2079B)


      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 <stdbool.h>
      9 #include <assert.h>
     10 #include <time.h>
     11 
     12 #define STR_LEN			16384
     13 #define FISH_VARIANTS	8
     14 #define FISHES_SIZE		9
     15 #define FISH_COMMON		6
     16 
     17 void make_fishes(size_t *fishes, const char *str);
     18 size_t sum_fishes(size_t *orig_fishes, int days);
     19 
     20 /* ****************************************************************** */
     21 
     22 void puzzle(const char *filename, size_t *result1, size_t *result2) {
     23 	FILE *infile = fopen(filename, "r");
     24 	if (infile == NULL) {
     25 		fprintf(stderr, "fopen() error: %s\n", strerror(errno));
     26 		return;
     27 	}
     28 
     29 	char buf[STR_LEN] = {0};
     30 	unsigned int line_num = 0;
     31 
     32 	size_t fishes[FISHES_SIZE] = {0};
     33 
     34 	while (fgets(buf, STR_LEN, infile) != NULL) {
     35 		make_fishes(fishes, buf);
     36 		++line_num;
     37 		bzero(buf, STR_LEN);
     38 	}
     39 
     40 	*result1 = sum_fishes(fishes, 80);
     41 	*result2 = sum_fishes(fishes, 256);
     42 
     43 	// mutiny! ignoring feof/ferror.
     44 	fclose(infile);
     45 }
     46 
     47 void make_fishes(size_t *fishes, const char *str) {
     48 	assert(fishes != NULL);
     49 	assert(str != NULL);
     50 	char *tmp = strndup(str, STR_LEN);
     51 	char *token = NULL;
     52 	assert(tmp != NULL);
     53 
     54 	while ((token = strsep(&tmp, ",")) != NULL) {
     55 		int val = atoi(token);
     56 		assert(val < FISH_VARIANTS);
     57 		fishes[val]++;
     58 	}
     59 
     60 	free(tmp);
     61 }
     62 
     63 size_t sum_fishes(size_t *orig_fishes, int days) {
     64 	assert(orig_fishes != NULL);
     65 	size_t fishes[FISHES_SIZE];
     66 	memcpy(fishes, orig_fishes, sizeof(size_t) * FISHES_SIZE);
     67 
     68 	for (int day = 1; day <= days; ++day) {
     69 		// took me an eternity to see the pattern
     70 		// thanks for help from friends from the #lobsters-advent
     71 		// fixed it without using matrices multiplication
     72 
     73 		// [a, b, c, d, e, f, g, h, i] -> [b, c, d, e, f, g, h+a, i, a]
     74 		size_t fish_0 = fishes[0];
     75 		for (int i = 0; i < FISH_VARIANTS; ++i) {
     76 			if (i == FISH_COMMON) {
     77 				fishes[i] = fishes[i+1] + fish_0;
     78 			} else {
     79 				fishes[i] = fishes[i+1];
     80 			}
     81 		}
     82 		fishes[FISH_VARIANTS] = fish_0;
     83 	}
     84 
     85 	size_t result = 0;
     86 	for (int i = 0; i < FISHES_SIZE; ++i) {
     87 		result += fishes[i];
     88 	}
     89 
     90 	return result;
     91 }