/** * Parse the input into a string of directions and a list of nodes and their child nodes * * @param {string[]} map The array of lines representing the map * @returns {[string, MapNodeTree]} A string of the directions to take and the node tree for the map */ export function ParseMap(map: string[]): [string, MapNodeTree] { const tree: MapNodeTree = {}; const directions = map.shift() || ""; // Discard empty line map.shift(); let nodeLine:string|undefined = ""; while(nodeLine = map.shift()) { const [id, leftNode, rightNode] = Array.from(nodeLine.matchAll(/(\w{3})/g), (match) => match[1]); if (!id || !leftNode || !rightNode) { throw new Error(`Failed to parse line: ${nodeLine}\n\tid: ${id}\n\tleftNode: ${leftNode}\n\trightNode: ${rightNode}`); } tree[id] = {L: leftNode, R: rightNode}; } return [directions, tree]; } /** * Find the ID of the next node to visit * * @param {string} directions The entire string of directions * @param {MapNodeTree} map A list of nodes and their child nodes * @param {keyof MapNodeTree} currentNode The ID of the node we're current at * @param {number} stepsTaken The amount of steps already taken in the trek * @returns {keyof MapNodeTree|undefined} The next node ID, or undefined if none was found */ export function GetNextNodeInMap(directions: string, map: MapNodeTree, currentNode: keyof MapNodeTree, stepsTaken: number): keyof MapNodeTree|undefined { let nextNodeID: keyof MapNodeTree|undefined = undefined; // Ensure the current node exists if (map[currentNode]) { // Get the next direction to travel in as a looping index of the directions string const nextDirection = directions[stepsTaken % directions.length] as "L"|"R"; // Store the next node ID nextNodeID = map[currentNode][nextDirection]; } return nextNodeID; } /** * An object representing a tree of nodes */ export type MapNodeTree = { /** The ID of the node */ [NodeID: string]: { /** The ID of the node to the left of this one */ L: string, /** The ID of the node to the right of this one */ R: string, }, };