Files
AdventOfCode2023/10/10.c

362 lines
8.4 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_FILE "input2.txt"
#define STRBUF_LEN 200
#define GRID_ROWS 5
#define GRID_COLS 5
/********************************************************/
// Linked List Functions
/********************************************************/
// Node structure
typedef struct ll_node {
void *data;
struct ll_node *next;
} ll_node;
// Linked list structure
typedef struct linked_list {
ll_node* head;
} linked_list;
void ll_init(linked_list* list) {
list->head = NULL;
}
// Function to create a new node
ll_node* ll_create_node(void *data) {
ll_node* new_node = (ll_node*)malloc(sizeof(ll_node));
if (new_node != NULL) {
new_node->data = data;
new_node->next = NULL;
}
return new_node;
}
// Function to add a node to the beginning of the list
void ll_prepend(linked_list* list, void *data) {
ll_node* new_node = ll_create_node(data);
if (new_node != NULL) {
new_node->next = list->head;
list->head = new_node;
}
}
// Function to add a node to the end of the list
void ll_append(linked_list* list, void *data) {
ll_node* newNode = ll_create_node(data);
if (newNode != NULL) {
if (list->head == NULL) {
list->head = newNode;
} else {
ll_node* current = list->head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
}
}
// Function to remove a node with a given value
void ll_remove(linked_list* list, void *data, bool (*compare_function)(void *, void*)) {
ll_node* current = list->head;
ll_node* prev = NULL;
while (current != NULL && !compare_function(current->data, data)) {
prev = current;
current = current->next;
}
if (current != NULL) {
if (prev != NULL) {
prev->next = current->next;
} else {
list->head = current->next;
}
free(current);
}
}
// Function to free the memory used by the linked list
void ll_free(linked_list* list) {
ll_node* current = list->head;
ll_node* next;
while (current != NULL) {
next = current->next;
free(current->data);
free(current);
current = next;
}
list->head = NULL;
}
uint64_t ll_len(linked_list* list)
{
uint64_t len = 0;
ll_node *current = list->head;
while (current != NULL)
{
len++;
current = current->next;
}
return len;
}
/**
* @brief Prints all elements in a linked list
*
* @param list
* @param print_data_func A function that prints the data of a node when
* passed the pointer to its data
*/
void print_list(linked_list *list, void (*print_data_func)(void *data))
{
ll_node* current = list->head;
while (current != NULL) {
print_data_func(current->data);
current = current->next;
}
}
/********************************************************/
// Implimentation Specific Linked List Functions
/********************************************************/
typedef struct _distance_data
{
int row;
int col;
int distance;
} distance_data;
void print_data_func(void *data)
{
distance_data *d = (distance_data *)data;
int row = d->row;
int col = d->col;
int distance = d->distance;
printf("R:%d C:%d D:%d\n", row, col, distance);
}
/********************************************************/
// Challenge functions
/********************************************************/
/**
* @brief Reads a file and loads the grid into
* an array of rows and columns
*/
void load_grid(FILE *file, char grid[GRID_ROWS][GRID_COLS])
{
char strbuf[STRBUF_LEN] = {0};
int i = 0;
for (i = 0; i < GRID_ROWS; i++)
{
fgets(strbuf, STRBUF_LEN, file);
memcpy(grid[i], strbuf, GRID_COLS);
}
}
/**
* @brief Finds the row and col idx of the 'S' char and places them in row_idx and col_idx
*
* @return true if S is found
* @return false if S is not found
*/
bool find_s(char grid[GRID_ROWS][GRID_COLS], int *row_idx, int *col_idx)
{
int r;
int c;
for (r = 0; r < GRID_ROWS; r++)
{
for (c = 0; c < GRID_ROWS; c++)
{
if (grid[r][c] == 'S')
{
*row_idx = r;
*col_idx = c;
return true;
}
}
}
return false;
}
/**
* @brief Populates a node on the linked list with information
* about a single nodes distance value
*/
void append_distance(int distance, int row, int col, linked_list *list)
{
distance_data *data = malloc(sizeof(distance_data));
data->row = row;
data->col = col;
data->distance = distance;
ll_append(list, data);
}
/**
* @brief Checks if the cell above should be populated, and populates it if so
*
* @return true if the cell was populated
* @return false if the cell was not populatd
*/
void populate_distance_above(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
{
int row = data->row;
int col = data->col;
int distance = data->distance;
if (!col) return;
char above = grid[row][col - 1];
if (above != '|' && above != '7' && above != 'F') return;
append_distance(distance + 1, row, col - 1, list);
}
/**
* @brief Checks if the cell to the left should be populated, and populates it if so
*
* @return true if the cell was populated
* @return false if the cell was not populatd
*/
void populate_distance_left(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
{
int row = data->row;
int col = data->col;
int distance = data->distance;
if (!row) return;
char left = grid[row - 1][col];
if (left != '-' && left != 'L' && left != 'F') return;
append_distance(distance + 1, row - 1, col, list);
}
/**
* @brief Checks if the cell to the right should be populated, and populates it if so
*
* @return true if the cell was populated
* @return false if the cell was not populatd
*/
void populate_distance_right(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
{
int row = data->row;
int col = data->col;
int distance = data->distance;
if (row == GRID_ROWS) return;
char right = grid[row + 1][col];
if (right != '-' && right != '7' && right != 'J') return;
append_distance(distance + 1, row + 1, col, list);
}
/**
* @brief Checks if the cell below should be populated, and populates it if so
*
* @param data
* @param list
* @param grid
* @return true if the cell was populated
* @return false if the cell was not populatd
*/
bool populate_distance_below(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
{
int row = data->row;
int col = data->col;
int distance = data->distance;
if (col == GRID_COLS) return false;
char below = grid[row][col + 1];
if (below != '|' && below != 'J' && below != 'L') return false;
append_distance(distance + 1, row, col + 1, list);
return true;
}
void populate_distances_around(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
{
int r = data->row;
int col = data->col;
int distance = data->distance;
populate_distance_above(data, list, grid);
populate_distance_left(data, list, grid);
populate_distance_right(data, list, grid);
populate_distance_below(data, list, grid);
}
/**
* @brief Traverses each node of a linked list and populates all distances around those nodes
*
* @param distance the NEW distance to populate
*/
void populate_distance_step(int distance, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
{
ll_node *current = list->head;
while (current != NULL)
{
}
}
int main(int argc, char **argv)
{
// Get filename as an argument, if there is one
char *path = (argc > 1) ? argv[1] : DEFAULT_FILE;
if (!path)
{
printf("Requires input file.\n");
return 1;
}
FILE *file = fopen(path, "r");
if (!file)
{
printf("Could not find file.");
return 1;
}
char grid[GRID_ROWS][GRID_COLS] = {0};
linked_list dist_list;
ll_init(&dist_list);
load_grid(file, grid);
int r = 0;
int c = 0;
if (!find_s(grid, &r, &c))
{
printf("Could not find S???\n");
return 1;
}
append_distance(0, r, c, &dist_list);
printf("%c", grid[r][c]);
return 0;
}