218 lines
6.1 KiB
C
218 lines
6.1 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#include "puzzle_input.h"
|
|
#include "day.h"
|
|
#include "queue.h"
|
|
#include "grid.h"
|
|
|
|
//#define DEBUG
|
|
|
|
#define QUEUE_MAX_SIZE 100
|
|
#define GRID_MAX_SIZE 11
|
|
|
|
typedef struct {
|
|
uint8_t energy_level;
|
|
uint8_t popped;
|
|
} octopus_t;
|
|
|
|
static point_t queue_data_g[QUEUE_MAX_SIZE] = {0};
|
|
static octopus_t grid_data_g[GRID_MAX_SIZE*GRID_MAX_SIZE] = {0};
|
|
|
|
parse_ret_t parse_octo_grid(char * buffer, void * data, uint16_t index) {
|
|
grid_t * grid = (grid_t *)data;
|
|
int16_t line_ndx = 0;
|
|
while (buffer[line_ndx] != '\0') {
|
|
octopus_t octo;
|
|
octo.energy_level = buffer[line_ndx] - '0';
|
|
octo.popped = 0;
|
|
grid_set_data(grid, index, line_ndx, &octo);
|
|
line_ndx++;
|
|
}
|
|
|
|
grid->width = line_ndx;
|
|
|
|
return PARSER_OK;
|
|
}
|
|
|
|
static grid_ret_t update_octo_energy_level(grid_t * grid, int ii, int jj) {
|
|
grid_ret_t ret;
|
|
octopus_t octo;
|
|
|
|
ret = grid_get_data(grid, ii, jj, &octo);
|
|
|
|
if (ret != GRID_OK) {
|
|
return ret;
|
|
}
|
|
octo.energy_level = octo.energy_level + 1;
|
|
|
|
ret = grid_set_data(grid, ii, jj, &octo);
|
|
|
|
if (ret != GRID_OK) {
|
|
return ret;
|
|
}
|
|
|
|
return GRID_OK;
|
|
}
|
|
|
|
static grid_ret_t set_octo_popped_state(grid_t * grid, int ii, int jj, uint8_t popped) {
|
|
grid_ret_t ret;
|
|
octopus_t octo;
|
|
|
|
ret = grid_get_data(grid, ii, jj, &octo);
|
|
|
|
if (ret != GRID_OK) {
|
|
return ret;
|
|
}
|
|
octo.popped = popped;
|
|
|
|
ret = grid_set_data(grid, ii, jj, &octo);
|
|
|
|
if (ret != GRID_OK) {
|
|
return ret;
|
|
}
|
|
|
|
return GRID_OK;
|
|
}
|
|
|
|
int day_11() {
|
|
parse_ret_t parse_ret = PARSER_OK;
|
|
grid_ret_t grid_ret = GRID_OK;
|
|
queue_ret_t queue_ret = QUEUE_OK;
|
|
queue_t queue = {0};
|
|
grid_t grid = {0};
|
|
uint16_t grid_height;
|
|
uint16_t flash_count = 0;
|
|
|
|
grid_init(&grid, GRID_MAX_SIZE, GRID_MAX_SIZE, sizeof(octopus_t), grid_data_g);
|
|
|
|
parse_ret = read_input_single_line("../inputs/day_11.txt", (void *) &grid, GRID_MAX_SIZE, parse_octo_grid,
|
|
&grid_height);
|
|
|
|
if (parse_ret != PARSER_OK) {
|
|
printf("Unable to parse input data: %d\n", parse_ret);
|
|
return -1;
|
|
}
|
|
|
|
if (grid_height == 0) {
|
|
printf("No data was parsed from file!\n");
|
|
return -2;
|
|
}
|
|
|
|
grid.height = grid_height;
|
|
|
|
for (int step = 0; step < 1000; step++) {
|
|
queue_init(&queue, queue_data_g, QUEUE_MAX_SIZE, sizeof(point_t));
|
|
|
|
for (int ii = 0; ii < grid.height; ii++) {
|
|
for (int jj = 0; jj < grid.width; jj++) {
|
|
octopus_t octo;
|
|
grid_ret = update_octo_energy_level(&grid, ii, jj);
|
|
|
|
if (grid_ret != GRID_OK) {
|
|
printf("Octo energy level update caused an error: %d\n", grid_ret);
|
|
return -3;
|
|
}
|
|
|
|
grid_ret = grid_get_data(&grid, ii, jj, &octo);
|
|
if (grid_ret != GRID_OK) {
|
|
printf("Unable to fetch octo: %d\n", grid_ret);
|
|
return -3;
|
|
}
|
|
|
|
if (octo.energy_level > 9) {
|
|
point_t point = {.ii = ii, .jj = jj};
|
|
set_octo_popped_state(&grid, ii, jj, 1);
|
|
if (queue_ret != QUEUE_OK) {
|
|
printf("Unable push point onto queue: %d\n", queue_ret);
|
|
return -4;
|
|
}
|
|
queue_ret = queue_push(&queue, &point);
|
|
}
|
|
}
|
|
}
|
|
|
|
while (queue.queued_elements > 0) {
|
|
point_t next_flash;
|
|
queue_ret = queue_pop(&queue, &next_flash);
|
|
if (queue_ret != QUEUE_OK) {
|
|
printf("Unable to pop from queue: %d\n", queue_ret);
|
|
return -4;
|
|
}
|
|
|
|
flash_count++;
|
|
|
|
for (int ii_ndx = next_flash.ii-1; ii_ndx <= next_flash.ii+1; ii_ndx++) {
|
|
for (int jj_ndx = next_flash.jj-1; jj_ndx <= next_flash.jj+1; jj_ndx++) {
|
|
octopus_t octo;
|
|
grid_ret = update_octo_energy_level(&grid, ii_ndx, jj_ndx);
|
|
|
|
if (grid_ret == GRID_INDEX_OUT_OF_RANGE) {
|
|
continue;
|
|
}
|
|
|
|
if (grid_ret != GRID_OK) {
|
|
printf("Unable to update octo: %d\n", grid_ret);
|
|
return -3;
|
|
}
|
|
|
|
grid_ret = grid_get_data(&grid, ii_ndx, jj_ndx, &octo);
|
|
if (grid_ret != GRID_OK) {
|
|
printf("Unable to fetch octo: %d\n", grid_ret);
|
|
return -3;
|
|
}
|
|
|
|
if (octo.energy_level > 9 && !octo.popped) {
|
|
point_t queue_flash = { .ii = ii_ndx, .jj = jj_ndx};
|
|
set_octo_popped_state(&grid, ii_ndx, jj_ndx, 1);
|
|
queue_ret = queue_push(&queue, &queue_flash);
|
|
|
|
if (queue_ret != QUEUE_OK) {
|
|
printf("Unable push point onto queue: %d\n", queue_ret);
|
|
return -4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Step %d:\n", step+1);
|
|
#endif
|
|
uint8_t step_popped_count = 0;
|
|
for (int ii = 0; ii < grid.height; ii++) {
|
|
for (int jj = 0; jj < grid.width; jj++) {
|
|
octopus_t octo = {0};
|
|
grid_get_data(&grid, ii, jj, &octo);
|
|
|
|
if (octo.popped) {
|
|
step_popped_count++;
|
|
octo.energy_level = 0;
|
|
octo.popped = 0;
|
|
grid_set_data(&grid, ii, jj, &octo);
|
|
}
|
|
#ifdef DEBUG
|
|
printf("%d", octo.energy_level);
|
|
#endif
|
|
}
|
|
#ifdef DEBUG
|
|
printf("\n");
|
|
#endif
|
|
}
|
|
#ifdef DEBUG
|
|
printf("\n\n");
|
|
#endif
|
|
|
|
if (step == 99) {
|
|
printf("PART 1: After 100 steps there were %d flashes!\n", flash_count);
|
|
}
|
|
|
|
if (step_popped_count == 100) {
|
|
printf("All octos flashed at the same time step %d", step+1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
} |