You will write a program that opens the file input.txt and finds the shortest path from the starting position to the end position. The elevation of the surrounding area constrains the path.
a is the lowest elevation and z is the highest elevation.S) and the target position for the best view (E). Your current position has elevation a, and the target position has elevation z.E, but to save energy for the rest of the trip home, you want to do it in as few steps as possible. You can move exactly one square up, down, left, or right during each step. Because a certain MIDN forgot their climbing gear at home, the elevation of the destination square can be, at most, one higher than the elevation of the current square. This means if you are at an elevation of height m, you can step to n but not to o. This also means that the elevation of the destination square can be much lower than that of your current square.You have two parts to this challenge:
S to the target location.a to the target location.Concatenate these answers in flag braces separated by a semicolon (flag{part1:part2}).
This challenging problem is aptly worth the points it is worth. This challenge tests your ability to implement a BFS algorithm with proper backtracking to find the shortest path.
We are using a DFS to solve this problem. Let's talk about data structures:
int. I could have used an unsigned integer, but with BFS/DFS algorithms, I like having a sanity check to ensure the number won't underflow.For the linked list, we need to know the position and the fewest steps to get to it. I made a struct to hold this information.
typedef struct node { int x, y, steps; struct node *next; } node;
We'll need to keep a global linked list containing the queue of nodes plus the visited nodes.
node *queue, *visited;
We also want to know the height and width of the board. We'll also store this globally so every function can see it.
int height, width;
With this out of the way, we can open the file and initialize data. We'll open the file as normal.
// Open file for reading FILE *file = fopen("input.txt", "r"); if (file == NULL) { printf("Could not open file.\n"); exit(
Once we have the file opened, we need to initialize the data. This involves reading the array into the map we created. This time, I chose to use fscanf() to get the string, but getline() works too.
// Read data for file int index = 0; map[index] = malloc(100); while (fscanf(file, "%s", map[index])
Once this is done, we must initialize the height and width of the map.
// Declare height and width of the heightmap height = index; width = strlen(map[0]);
Once this is initialized, the processing can begin. We do almost all this in sub-functions, so we'll discuss the looping mechanism in this part and the processing in the next.
We must parse through all the data for both parts. In each part, we check for something different:
S.For the BFS algorithm, we simply check to ensure that any finish result is less than the current best case. If it is, we update the best case.
// Find Starting coordinates and calculate shortest path int part1 = INT_MAX; int part2 = INT_MAX; for (int y = 0; y < height; y++) { for (
From here, we can parse the data and perform the BFS algorithm.
Here comes the challenge. We need to define a function BFS() that takes a coordinate and returns the shortest path to the end.
First, we must free queue and visited because we are starting a new BFS algorithm. This ensures the lists are empty.
// Free memory of the queue and visited free_memory(queue); free_memory(visited); queue = visited = NULL;
Next, we need to make a new node for the starting position. We'll build nodes often enough that it's worthy of its own function. This function should take the three values we need to make a node, allocate a new one, and return a pointer to the node.
node *buildNode(int x, int y, int steps) { node *new_node = malloc(sizeof(node)); new_node->x = x;
We'll use this to make a new node for the starting position. At the same time, we'll start our queue with this node.
// Create new node node *start = buildNode(x, y, 0); // Add starting node to the queue queue = start;
We are going to run the BFS algorithm until the queue is empty. When the queue is empty, we have no more nodes to check. Since BFS doesn't require backtracking, we can make this a simple while loop.
while (queue != NULL) { /* BFS algorithm */ }
We need to get the data from the current node. We'll store this in variables for ease of use.
// Get data from current node int x = queue->x; int y = queue->y; int value = getValue(x, y); int steps = queue->steps
We introduce a new function getValue that finds the value of that position in the map.
int getValue(int x, int y) { char value = map[y][x]; switch (value) { case
S as 0 and E as 25?We need to remove the current node from the queue. We should also add the current node to the visited list.
// Remove node from the queue node *current = queue; queue = queue->next; current->next = NULL; // Add current node to the visited queue current->next = visited; visited = current;
We need to iterate through the current node's neighbors. To represent the directional arrays for the neighbors, we can define dx and dy.
// Neighbors coordinates int dx[] = {1, 0, -1, 0}; int dy[] = {0, 1
At each iteration, we need to do the following checks:
E). If so, return the number of steps.// Find neighbors for (int i = 0; i < 4; i++) { // Get neighbor coordinates int nx = x + dx[i];
We made two new functions here.
The first function is inQueue(), which checks if the node is in the queue.
int inQueue(node *curr) { // Check if node is in the queue node *ptr = queue; while (ptr != NULL) { if (
If we reach the end of the queue and do not return a value, there is no path to the end. In this case, we should return INT_MAX to indicate that there is no path.
This is everything we need to execute a BFS algorithm. We can use this to print the flag.
To print the flag, we simply combine the answers from the two parts.
printf("flag{%d:%d}\n", part1, part2);
Once we're done, we free the memory. map is a 2D array, so we need to free each row individually. We also need to free our linked lists and close the file.
// Free memory for (int i = 0; i < index + 1; i++) free(map[i]); free_memory(visited);
We define free_memory() to free a Linked List.
void free_memory(node *list) { // Free memory of the list while (list) { node *temp = list; list = list->next; free
Running this method will return the flag! This method will take some time to run, depending on the machine. This method has to run a BFS algorithm for every a in the map. BFS is an O(V + E) algorithm, so the overall time is O(V + E * a). This is a very large number, so running will take some time.
The full solution is below:
#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node { int x
The second function is enqueue(), which adds a node to the back of the queue.
void enqueue(node **list, node *n) { if (*list == NULL) { // If list is empty *list = n; } else { // else add node to the end of the list node *current = *list; while (current->next != NULL) current = current->next; current->next = n; } }