Runnin' the Werk : An Algorithm of Route Optimization

Runnin' the Werk : An Algorithm of Route Optimization

The "Route Optimization" problem is a classic application of optimization algorithms, particularly the Traveling Salesman Problem (TSP). In our case, we’ll call it the D*pe-- (sorry), Werk Runner Problem (WRP). In this problem, a werk runner needs to find the shortest possible route that visits a set of blocks; and returns to the starting block. While the werk game is likely not running algorithms for its werk runners (or maybe they are?); on scheduled deliveries, securing the bag, and promptly returning that bag to the connect or plug is a part of the job description of the werk runner. This means route optimization is a necessity for the runner, the connect, and/or plug.

Algorithmic Approach

An algorithm for the werk game cannot be too global; specifically in the case of a werk runner. The runner needs to be able to make decisions that optimize his chance for success in the moment: considering long-term benefits beyond running the werk is not a concern for the werk runner.

The correct approach for our werk runner would be the "greedy approach". A "greedy approach" is a problem-solving strategy that makes the locally optimal choice at each step with the hope of finding a global optimum. In other words, it focuses on immediate gains and makes decisions that seem best at the current moment without considering the potential long-term consequences.

Coding the Optimization of Routes

The above class is defined with the Manhattan Distance formula in mind. The Manhattan distance, also known as the "taxicab distance" or "L1 distance," is a metric used to measure the distance between two points in a grid-based system, such as a city grid. It is named after the grid-like layout of streets in Manhattan, New York City, where traveling from one point to another often involves moving along city blocks at right angles.

The Manhattan distance between two points (x1, y1) and (x2, y2) in a 2D grid is calculated as follows:

Below we define a variable, 'streetBlocks', as an array taking the StreetBlock object with defined arguments.

Sliding Out with the Werk

The first thing our Werk runner needs to know is the distance of the routes.

Then the runner starts on his route to deliver the werk. He needs to stay on the most optimized route, and be mindful of manipulated routes(detours, street signs that point to the wrong street, etc) or he could risk not only being late for the delivery but also not arriving at all. This is where the optimized route algorithm comes into play.

Explanation of Algorithm

The code starts with an initial route, continuously finds the nearest unvisited street block, and adds it to the optimized route. Under a specific condition, it allows the route to be manipulated by switching the order of the first two blocks. The result is an optimized route that should minimize the overall distance traveled.
const initialRoute = [...blocks];: It creates a copy of the original blocks array, ensuring that the original data remains unaltered. The initialRoute array will be used to track the initial state of the street blocks.

  1. const optimizedRoute = [initialRoute[0]];: It initializes the optimizedRoute array with the first street block from the initialRoute. The optimization process starts from this block.

  2. let routeManipulated = false;: This variable is used to track whether the route has been manipulated. It is initially set to false.

  3. The code enters a while loop that continues until the optimizedRoute includes all the street blocks in the blocks array. In other words, it continues until the optimized route is complete.

  4. Inside the loop, it initializes variables shortestDistance to a very large value (using Number.MAX_VALUE) and nearestBlock to null. These variables will be used to keep track of the nearest unvisited street block.

  5. It then iterates through the initialRoute to find the nearest unvisited street block. For each block, it calculates the distance from the last block in the optimizedRoute using the Manhattan distance formula.

  6. It checks if the current street block is closer than the previously found nearest street block. If so, it updates shortestDistance and sets nearestBlock to the current block.

  7. After finding the nearest unvisited street block, it checks whether the route should be manipulated. This manipulation occurs only if routeManipulated is false, and the optimizedRoute contains exactly two blocks. In this case, it switches the order of the first two blocks in the optimizedRoute. This is a unique condition for route manipulation.

  8. Finally, the nearest street block (either the originally found one or the manipulated one) is added to the optimizedRoute.

  9. Once the while loop is complete, the function returns the optimizedRoute, which represents the optimized order in which to visit the street blocks.

Returning with the Bag: the Metrics

When our runner gets back to the connect/plug to drop off the bag, the optimizeRoute and calculateTotalDistance methods can be used to observe the routes the runner took and get the distance traveled.

The console would print the order of the blocks the runner took in delivering the werk, and the distance traveled. Talking about next level of keeping of tabs on your werkers!