diff --git a/c/2024/8/resonant_collinearity.c b/c/2024/8/resonant_collinearity.c new file mode 100644 index 0000000..2a4b457 --- /dev/null +++ b/c/2024/8/resonant_collinearity.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include + +#include "../../lib/aoc.h" + +typedef int Position[2]; + +typedef struct Map { + char *grid; + int width; + int height; + char signal; + int antennas[1000]; + int antenna_count; +} Map; + +void position_from_index(Map *map, int index, Position *p) { + (*p)[0] = index % map->width; + (*p)[1] = index / map->width; +} + +int index_from_position(Map *map, Position p) { + return p[0] + p[1] * map->width; +} + +bool position_inbounds(Map *map, Position p) { + return + p[0] >= 0 && + p[1] >= 0 && + p[0] < map->width - 1 && + p[1] < map->height; +} + +void calculate_antinodes(Map *map, char *antinodes_grid, bool resonant) { + int index; + for (int i = 0; i < map->antenna_count; i++) { + Position first_antenna; + position_from_index(map, map->antennas[i], &first_antenna); + for (int j = 0; j < i; j++) { + Position second_antenna; + position_from_index(map, map->antennas[j], &second_antenna); + + if (resonant) { + Position antinode; + + antinode[0] = first_antenna[0]; + antinode[1] = first_antenna[1]; + + while (position_inbounds(map, antinode)) { + index = index_from_position(map, antinode); + antinodes_grid[index] = '#'; + antinode[0] = antinode[0] + first_antenna[0] - second_antenna[0]; + antinode[1] = antinode[1] + first_antenna[1] - second_antenna[1]; + } + + antinode[0] = second_antenna[0]; + antinode[1] = second_antenna[1]; + + while (position_inbounds(map, antinode)) { + index = index_from_position(map, antinode); + antinodes_grid[index] = '#'; + antinode[0] = antinode[0] + second_antenna[0] - first_antenna[0]; + antinode[1] = antinode[1] + second_antenna[1] - first_antenna[1]; + } + + } else { + Position first_antinode, second_antinode; + first_antinode[0] = first_antenna[0] + first_antenna[0] - second_antenna[0]; + first_antinode[1] = first_antenna[1] + first_antenna[1] - second_antenna[1]; + + if (position_inbounds(map, first_antinode)) { + index = index_from_position(map, first_antinode); + antinodes_grid[index] = '#'; + } + + second_antinode[0] = second_antenna[0] + second_antenna[0] - first_antenna[0]; + second_antinode[1] = second_antenna[1] + second_antenna[1] - first_antenna[1]; + + if (position_inbounds(map, second_antinode)) { + index = index_from_position(map, second_antinode); + antinodes_grid[index] = '#'; + } + } + } + } +} + +int main() { + char *input = aoc_read_input(); + int input_size = strlen(input); + + Map master_map; + master_map.grid = input; + master_map.width = strchr(input, '\n') - input + 1; + master_map.height = input_size / master_map.width; + + char *empty_grid = malloc(input_size + 1); + for (int i = 0; i < input_size; i++) { + empty_grid[i] = '.'; + if (i % master_map.width == master_map.width - 1) empty_grid[i] = '\n'; + } + empty_grid[input_size] = '\0'; + + char *antinode_grid = malloc(input_size + 1); + strcpy(antinode_grid, empty_grid); + + char *resonant_antinode_grid = malloc(input_size + 1); + strcpy(resonant_antinode_grid, empty_grid); + + Map maps[64]; + for (int i = 0; i < 64; i++) { + maps[i].grid = malloc(input_size + 1); + strcpy(maps[i].grid, empty_grid); + maps[i].width = master_map.width; + maps[i].height = master_map.height; + if (i < 26) { + maps[i].signal = i + 'a'; + } else if (i < 52) { + maps[i].signal = i - 26 + 'A'; + } else { + maps[i].signal = i - 52 + '0'; + } + } + + for (int i = 0; i < input_size; i++) { + char c = master_map.grid[i]; + if (c == '.' || c == '\n') continue; + + int map_index; + if (c >= 'a' && c <= 'z') map_index = c - 'a'; + else if (c >= 'A' && c <= 'Z') map_index = c + 26 - 'A'; + else map_index = c + 52 - '0'; + + maps[map_index].antennas[maps[map_index].antenna_count++] = i; + } + + for (int i = 0; i < 64; i++) { + calculate_antinodes(&(maps[i]), antinode_grid, false); + } + + int antinode_count = 0; + for (int i = 0; i < input_size; i++) { + if (antinode_grid[i] == '#') antinode_count++; + } + + printf("Part 1: %d\n", antinode_count); + + for (int i = 0; i < 64; i++) { + calculate_antinodes(&(maps[i]), resonant_antinode_grid, true); + } + + int resonant_antinode_count = 0; + for (int i = 0; i < input_size; i++) { + if (resonant_antinode_grid[i] == '#') resonant_antinode_count++; + } + printf("Part 2: %lld\n", resonant_antinode_count); + + free(empty_grid); + free(antinode_grid); + free(resonant_antinode_grid); + for (int i = 0; i < 64; i++) free(maps[i].grid); + + aoc_free(); + return 0; +}