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
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; |
|
} |
|
}
|
|
|