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.
234 lines
6.0 KiB
234 lines
6.0 KiB
3 years ago
|
#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;
|
||
|
}
|
||
|
}
|