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