advent2021

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

puzzle.c (2608B)


      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 <ctype.h>
     10 #include <limits.h>
     11 
     12 #define STR_LEN 1024
     13 #define GRID_WIDTH 10
     14 #define GRID_HEIGHT 10
     15 #define STEPS 100
     16 
     17 typedef int octopuses_t[GRID_HEIGHT][GRID_WIDTH];
     18 
     19 void step(octopuses_t *octopuses);
     20 void print(octopuses_t *octopuses);
     21 void light(octopuses_t *octopuses, int x, int y);
     22 void process(octopuses_t *octopuses, int x, int y);
     23 int normalize(octopuses_t *octopuses);
     24 
     25 void puzzle(const char *filename, long long *result1, long long *result2) {
     26 	FILE *infile = fopen(filename, "r");
     27 	if (infile == NULL) {
     28 		fprintf(stderr, "fopen() error: %s\n", strerror(errno));
     29 		return;
     30 	}
     31 
     32 	char buf[STR_LEN] = {0};
     33 	unsigned int line_num = 0;
     34 	octopuses_t octopuses = {0};
     35 
     36 	*result1 = 0;
     37 	*result2 = 0;
     38 
     39 	while (fgets(buf, STR_LEN, infile) != NULL) {
     40 		size_t len = strlen(buf);
     41 		assert(len >= GRID_WIDTH);
     42 		for (int i = 0; i < GRID_WIDTH; ++i) {
     43 			assert(isdigit((int)buf[i]));
     44 			octopuses[line_num][i] = buf[i] - '0';
     45 		}
     46 		++line_num;
     47 		bzero(buf, STR_LEN);
     48 	}
     49 
     50 	for (int s = 1; s < INT_MAX; ++s) {
     51 		step(&octopuses);
     52 		int flashes = normalize(&octopuses);
     53 		if (s <= STEPS) {
     54 			*result1 += flashes;
     55 		}
     56 		if (flashes == GRID_WIDTH*GRID_HEIGHT) {
     57 			*result2 = s;
     58 		}
     59 		if (*result1 > 0 && *result2 > 0) {
     60 			break;
     61 		}
     62 	}
     63 
     64 	// mutiny! ignoring feof/ferror.
     65 	fclose(infile);
     66 }
     67 
     68 void step(octopuses_t *octopuses) {
     69 	for (int y = 0; y < GRID_HEIGHT; ++y) {
     70 		for (int x = 0; x < GRID_WIDTH; ++x) {
     71 			process(octopuses, x, y);
     72 		}
     73 	}
     74 }
     75 
     76 void process(octopuses_t *octopuses, int x, int y) {
     77 	int o = ++(*octopuses)[y][x];
     78 	if (o == 10) {
     79 		light(octopuses, x, y);
     80 	}
     81 }
     82 
     83 void light(octopuses_t *octopuses, int x, int y) {
     84 	if (y > 0) process(octopuses, x, y-1);
     85 	if (y < GRID_HEIGHT-1) process(octopuses, x, y+1);
     86 	if (x > 0) {
     87 		process(octopuses, x-1, y);
     88 		if (y > 0) process(octopuses, x-1, y-1);
     89 		if (y < GRID_HEIGHT-1) process(octopuses, x-1, y+1);
     90 	}
     91 	if (x < GRID_WIDTH-1) {
     92 		process(octopuses, x+1, y);
     93 		if (y > 0) process(octopuses, x+1, y-1);
     94 		if (y < GRID_HEIGHT-1) process(octopuses, x+1, y+1);
     95 	}
     96 }
     97 
     98 int normalize(octopuses_t *octopuses) {
     99 	int flashes = 0;
    100 	for (int y = 0; y < GRID_HEIGHT; ++y) {
    101 		for (int x = 0; x < GRID_WIDTH; ++x) {
    102 			if ((*octopuses)[y][x] > 9) {
    103 				(*octopuses)[y][x] = 0;
    104 				++flashes;
    105 			}
    106 		}
    107 	}
    108 	return flashes;
    109 }
    110 
    111 void print(octopuses_t *octopuses) {
    112 	for (int y = 0; y < GRID_HEIGHT; ++y) {
    113 		for (int x = 0; x < GRID_WIDTH; ++x) {
    114 			printf("%2d", (*octopuses)[y][x]);
    115 		}
    116 		printf("\n");
    117 	}
    118 }