My solutions to the advent of code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

233 lines
6.0 KiB

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_RESET "\x1b[0m"
#define ANSI_COLOR_BOLD "\x1b[1m"
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
typedef struct Square Square;
typedef struct SquareList SquareList;
struct Square{
unsigned int risk;
Square *previous;
unsigned int distanceFromStart;
Square *up;
Square *down;
Square *left;
Square *right;
bool onShortestPath;
bool used;
};
struct SquareList{
Square *square;
SquareList *next;
};
SquareList* newSqareListItem(Square *square){
SquareList *newSquare = malloc(sizeof(SquareList));
newSquare->square = square;
newSquare->next = NULL;
return newSquare;
}
int countRows(FILE *fp){
unsigned int lines=0;
while (EOF != (fscanf(fp, "%*[^\n]"), fscanf(fp,"%*c")))
++lines;
return lines;
}
int countCols(FILE *fp){
unsigned int lineLength=0;
char ch = fgetc(fp);
while ( ch != '\n' ){
lineLength++;
ch = fgetc(fp);
}
return lineLength;
}
void printGrid( unsigned int cols, unsigned int rows, Square **grid){
for ( unsigned int row = 0; row < rows; row++ ){
if ( row % ( rows / 5 ) == 0 ) printf("\n");
for ( unsigned int col = 0; col < cols; col++ ){
if ( col % ( cols / 5 ) == 0 ) printf(" ");
if ( grid[col][row].onShortestPath ) printf(ANSI_COLOR_RED);
if ( col < cols / 5 && row < rows/5 ) printf(ANSI_COLOR_BOLD);
printf("%i ", grid[col][row].risk);
if ( grid[col][row].onShortestPath ) printf(ANSI_COLOR_RESET);
if ( col < cols / 5 && row < rows/5 ) printf(ANSI_COLOR_RESET);
}
printf("\n");
}
}
void maybeUpdate(Square *current, Square *adjacent, SquareList *lastEndItem){
if ( adjacent == NULL ) return ;
if ( current->distanceFromStart + adjacent->risk < adjacent->distanceFromStart ){
adjacent->distanceFromStart = current->distanceFromStart + adjacent->risk;
adjacent->previous = current;
lastEndItem->next = newSqareListItem(adjacent);
}
}
void markAdjacent(Square *current, SquareList *firstEndItem){
SquareList *lastItem = firstEndItem;
while ( lastItem->next != NULL ) lastItem = lastItem->next;
unsigned int currentDistance = current->distanceFromStart;
maybeUpdate(current, current->up, lastItem);
if ( lastItem->next != NULL ) lastItem = lastItem->next;
maybeUpdate(current, current->down, lastItem);
if ( lastItem->next != NULL ) lastItem = lastItem->next;
maybeUpdate(current, current->left, lastItem);
if ( lastItem->next != NULL ) lastItem = lastItem->next;
maybeUpdate(current, current->right, lastItem);
}
Square* getLowestEndScoredSquare( SquareList *current ){
Square *lowest = current->square;
while ( current != NULL ){
if ( ( current->square->distanceFromStart < lowest->distanceFromStart ) ){
lowest = current->square;
}
current = current -> next;
}
return lowest;
}
SquareList* pruneEndList( SquareList *first ){
// First item is a sliphtly special case
while ( first != NULL && first->square->used ){
first = first->next;
}
if ( first == NULL ) return NULL;
SquareList *previous = first;
SquareList *current = first->next;
while ( current != NULL ){
while ( current->square->used ){
previous->next = current->next;
current = previous->next;
}
previous = current;
current = current->next;
}
return first;
}
unsigned int endListLength( SquareList *current ){
unsigned int count = 0;
while ( current != NULL ){
count++;
current = current->next;
}
return count;
}
int main( int argc, char *argv[] ){
if( argc == 2 ) {
FILE *fp=fopen(argv[1], "r");
unsigned int cols=countCols(fp);
rewind(fp);
unsigned int rows=countRows(fp);
rewind(fp);
Square **grid=(Square**)malloc( cols * 5 * sizeof(Square *));
for(unsigned int i=0; i<=rows*5;i++) {
grid[i]=(Square*)malloc( rows * 5 * sizeof(Square));
memset(grid[i], 0, sizeof(Square) * rows * 5);
}
char ch;
unsigned int row=0, col=0;
while ( !feof(fp) && fscanf(fp, "%c", &ch) ){
if ( ch == '\n' ){
col = 0;
row++;
continue;
}
for (unsigned int j=0; j < 5; j++){
for (unsigned int i=0; i < 5 ; i++){
unsigned int realcol = col + (i*cols), realrow = row + (j*rows);
grid[realcol][realrow].risk = (( ch - '0') + i + j ) % 9;
if ( grid[realcol][realrow].risk == 0 ) grid[realcol][realrow].risk = 9;
grid[realcol][realrow].distanceFromStart = ~0;
grid[realcol][realrow].up = ( realrow > 0 ) ? &grid[realcol][realrow-1] : NULL;
grid[realcol][realrow].down = ( realrow < rows*5 - 1 ) ? &grid[realcol][realrow+1] : NULL;
grid[realcol][realrow].left = ( realcol > 0 ) ? &grid[realcol-1][realrow] : NULL;
grid[realcol][realrow].right = ( realcol < cols*5 - 1 ) ? &grid[realcol+1][realrow] : NULL;
grid[realcol][realrow].onShortestPath = false;
grid[realcol][realrow].used = false;
}
}
col++;
}
//grid[cols*5-1][rows*5-1].onShortestPath = true;
//printGrid(cols*5, rows*5, grid);
Square *current = &grid[0][0];
SquareList *firstEndItem = newSqareListItem(current);
unsigned int i = 0;
while (true){
markAdjacent(current, firstEndItem);
current->used = true;
if ( current == &grid[cols*5-1][rows*5-1] ) break;
firstEndItem = pruneEndList(firstEndItem);
current = getLowestEndScoredSquare(firstEndItem);
i++;
}
//while ( firstEndItem != NULL ){
// firstEndItem->square->onShortestPath = true;
// printf("Risk: %i Length: %i\n", firstEndItem->square->risk, firstEndItem->square->distanceFromStart);
// firstEndItem = firstEndItem->next;
//}
unsigned long total = 0;
while ( true ){
current->onShortestPath = true;
total += current->risk;
if ( current != &grid[0][0] )
current = current->previous;
else
break;
}
printGrid(cols*5, rows*5, grid);
//printGrid(cols*5, rows*5, grid);
//grid[0][0].distanceFromStart = 0;
printf("Total risk: %lu\n", total - grid[0][0].risk);
//markAdjacent(grid, 0, 0);
fclose(fp);
return 0;
} else {
printf("You need to provide a file\n");
return 1;
}
}