Complete Day 10 Part 1
This commit is contained in:
317
10/10.c
317
10/10.c
@@ -4,154 +4,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define DEFAULT_FILE "input2.txt"
|
#define DEFAULT_FILE "input.txt"
|
||||||
#define STRBUF_LEN 200
|
#define STRBUF_LEN 200
|
||||||
#define GRID_ROWS 5
|
// #define GRID_ROWS 5
|
||||||
#define GRID_COLS 5
|
// #define GRID_COLS 5
|
||||||
|
#define GRID_ROWS 140
|
||||||
/********************************************************/
|
#define GRID_COLS 140
|
||||||
// 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
|
* @brief Reads a file and loads the grid into
|
||||||
@@ -194,37 +52,29 @@ bool find_s(char grid[GRID_ROWS][GRID_COLS], int *row_idx, int *col_idx)
|
|||||||
return false;
|
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
|
* @brief Checks if the cell above should be populated, and populates it if so
|
||||||
*
|
*
|
||||||
* @return true if the cell was populated
|
* @return true if the cell was populated
|
||||||
* @return false if the cell was not populatd
|
* @return false if the cell was not populatd
|
||||||
*/
|
*/
|
||||||
void populate_distance_above(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
|
bool populate_distance_above(int row, int col, int distance_grid[GRID_ROWS][GRID_COLS], char grid[GRID_ROWS][GRID_COLS])
|
||||||
{
|
{
|
||||||
int row = data->row;
|
if (!row) return false;
|
||||||
int col = data->col;
|
|
||||||
int distance = data->distance;
|
|
||||||
|
|
||||||
if (!col) return;
|
char c = grid[row][col];
|
||||||
|
if (c != '|' && c != 'J' && c != 'L' && c != 'S') return false;
|
||||||
|
|
||||||
char above = grid[row][col - 1];
|
// Check for existing distance
|
||||||
if (above != '|' && above != '7' && above != 'F') return;
|
char above = grid[row - 1][col];
|
||||||
|
if (above != '|' && above != '7' && above != 'F') return false;
|
||||||
|
|
||||||
append_distance(distance + 1, row, col - 1, list);
|
// Check for existing distance
|
||||||
|
if (distance_grid[row - 1][col] != -1) return false;
|
||||||
|
|
||||||
|
int distance = distance_grid[row][col];
|
||||||
|
distance_grid[row - 1][col] = distance + 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,18 +83,22 @@ void populate_distance_above(distance_data *data, linked_list *list, char grid[G
|
|||||||
* @return true if the cell was populated
|
* @return true if the cell was populated
|
||||||
* @return false if the cell was not populatd
|
* @return false if the cell was not populatd
|
||||||
*/
|
*/
|
||||||
void populate_distance_left(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
|
bool populate_distance_left(int row, int col, int distance_grid[GRID_ROWS][GRID_COLS], char grid[GRID_ROWS][GRID_COLS])
|
||||||
{
|
{
|
||||||
int row = data->row;
|
if (!col) return false;
|
||||||
int col = data->col;
|
|
||||||
int distance = data->distance;
|
|
||||||
|
|
||||||
if (!row) return;
|
char c = grid[row][col];
|
||||||
|
if (c != '-' && c != '7' && c != 'J' && c != 'S') return false;
|
||||||
|
|
||||||
char left = grid[row - 1][col];
|
char left = grid[row][col - 1];
|
||||||
if (left != '-' && left != 'L' && left != 'F') return;
|
if (left != '-' && left != 'L' && left != 'F') return false;
|
||||||
|
|
||||||
append_distance(distance + 1, row - 1, col, list);
|
// Check for existing distance
|
||||||
|
if (distance_grid[row][col - 1] != -1) return false;
|
||||||
|
|
||||||
|
int distance = distance_grid[row][col];
|
||||||
|
distance_grid[row][col - 1] = distance + 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,18 +107,22 @@ void populate_distance_left(distance_data *data, linked_list *list, char grid[GR
|
|||||||
* @return true if the cell was populated
|
* @return true if the cell was populated
|
||||||
* @return false if the cell was not populatd
|
* @return false if the cell was not populatd
|
||||||
*/
|
*/
|
||||||
void populate_distance_right(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
|
bool populate_distance_right(int row, int col, int distance_grid[GRID_ROWS][GRID_COLS], char grid[GRID_ROWS][GRID_COLS])
|
||||||
{
|
{
|
||||||
int row = data->row;
|
if (row == GRID_ROWS) return false;
|
||||||
int col = data->col;
|
char c = grid[row][col];
|
||||||
int distance = data->distance;
|
if (c != '-' && c != 'L' && c != 'F' && c != 'S') return false;
|
||||||
|
|
||||||
if (row == GRID_ROWS) return;
|
// Check for connecting pipe
|
||||||
|
char right = grid[row][col + 1];
|
||||||
|
if (right != '-' && right != '7' && right != 'J') return false;
|
||||||
|
|
||||||
char right = grid[row + 1][col];
|
// Check for existing distance
|
||||||
if (right != '-' && right != '7' && right != 'J') return;
|
if (distance_grid[row][col + 1] != -1) return false;
|
||||||
|
|
||||||
append_distance(distance + 1, row + 1, col, list);
|
int distance = distance_grid[row][col];
|
||||||
|
distance_grid[row][col + 1] = distance + 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,44 +134,73 @@ void populate_distance_right(distance_data *data, linked_list *list, char grid[G
|
|||||||
* @return true if the cell was populated
|
* @return true if the cell was populated
|
||||||
* @return false if the cell was not populatd
|
* @return false if the cell was not populatd
|
||||||
*/
|
*/
|
||||||
bool populate_distance_below(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
|
bool populate_distance_below(int row, int col, int distance_grid[GRID_ROWS][GRID_COLS], char grid[GRID_ROWS][GRID_COLS])
|
||||||
{
|
{
|
||||||
int row = data->row;
|
|
||||||
int col = data->col;
|
|
||||||
int distance = data->distance;
|
|
||||||
|
|
||||||
if (col == GRID_COLS) return false;
|
if (col == GRID_COLS) return false;
|
||||||
|
|
||||||
char below = grid[row][col + 1];
|
char c = grid[row][col];
|
||||||
|
if (c != '|' && c != 'F' && c != '7' && c != 'S') return false;
|
||||||
|
|
||||||
|
// Check for connecting pipe
|
||||||
|
char below = grid[row + 1][col];
|
||||||
|
|
||||||
if (below != '|' && below != 'J' && below != 'L') return false;
|
if (below != '|' && below != 'J' && below != 'L') return false;
|
||||||
|
|
||||||
append_distance(distance + 1, row, col + 1, list);
|
// Check for existing distance
|
||||||
|
if (distance_grid[row + 1][col] != -1) return false;
|
||||||
|
|
||||||
|
int distance = distance_grid[row][col];
|
||||||
|
distance_grid[row + 1][col] = distance + 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void populate_distances_around(distance_data *data, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
|
bool populate_distances_around(int row, int col, int distance_grid[GRID_ROWS][GRID_COLS], char grid[GRID_ROWS][GRID_COLS])
|
||||||
{
|
{
|
||||||
int r = data->row;
|
bool progress_made = false;
|
||||||
int col = data->col;
|
if (populate_distance_above(row, col, distance_grid, grid)) progress_made = true;
|
||||||
int distance = data->distance;
|
if (populate_distance_left(row, col, distance_grid, grid)) progress_made = true;
|
||||||
populate_distance_above(data, list, grid);
|
if (populate_distance_right(row, col, distance_grid, grid)) progress_made = true;
|
||||||
populate_distance_left(data, list, grid);
|
if (populate_distance_below(row, col, distance_grid, grid)) progress_made = true;
|
||||||
populate_distance_right(data, list, grid);
|
return progress_made;
|
||||||
populate_distance_below(data, list, grid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Traverses each node of a linked list and populates all distances around those nodes
|
* @brief Preform pass of entire grid and populate next step of distances
|
||||||
*
|
*
|
||||||
* @param distance the NEW distance to populate
|
* @param distance the current distance to populate around
|
||||||
*/
|
*/
|
||||||
void populate_distance_step(int distance, linked_list *list, char grid[GRID_ROWS][GRID_COLS])
|
bool populate_distance_step(int current_distance, int distance_grid[GRID_ROWS][GRID_COLS], char grid[GRID_ROWS][GRID_COLS])
|
||||||
{
|
{
|
||||||
ll_node *current = list->head;
|
int row = 0;
|
||||||
|
int col = 0;
|
||||||
|
bool progress_made = false;
|
||||||
|
|
||||||
while (current != NULL)
|
for (row = 0; row < GRID_ROWS; row++)
|
||||||
{
|
{
|
||||||
|
for (col = 0; col < GRID_COLS; col++)
|
||||||
|
{
|
||||||
|
if (distance_grid[row][col] == current_distance)
|
||||||
|
{
|
||||||
|
progress_made = populate_distances_around(row, col, distance_grid, grid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return progress_made;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_distance_map(int distance_grid[GRID_ROWS][GRID_COLS])
|
||||||
|
{
|
||||||
|
int row = 0;
|
||||||
|
int col = 0;
|
||||||
|
for (row = 0; row < GRID_ROWS; row++)
|
||||||
|
{
|
||||||
|
for (col = 0; col < GRID_COLS; col++)
|
||||||
|
{
|
||||||
|
if (distance_grid[row][col] != -1) printf(" %0.2d", distance_grid[row][col]);
|
||||||
|
else printf(" .");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,9 +224,8 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char grid[GRID_ROWS][GRID_COLS] = {0};
|
char grid[GRID_ROWS][GRID_COLS] = {0};
|
||||||
|
int distance_grid[GRID_ROWS][GRID_COLS];
|
||||||
linked_list dist_list;
|
memset(distance_grid, -1, sizeof(distance_grid));
|
||||||
ll_init(&dist_list);
|
|
||||||
|
|
||||||
load_grid(file, grid);
|
load_grid(file, grid);
|
||||||
|
|
||||||
@@ -352,11 +238,20 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
append_distance(0, r, c, &dist_list);
|
int current_distance = 0;
|
||||||
|
distance_grid[r][c] = 0;
|
||||||
|
|
||||||
|
bool progress_made = true;
|
||||||
|
while (progress_made)
|
||||||
|
{
|
||||||
|
progress_made = populate_distance_step(current_distance, distance_grid, grid);
|
||||||
|
printf("---\n");
|
||||||
|
current_distance++;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_distance_map(distance_grid);
|
||||||
printf("%c", grid[r][c]);
|
|
||||||
|
printf("Longest route: %d", current_distance);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user