123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- import { LoadInput } from "../common.ts";
- const tests_EZ = [
- "RL",
- "",
- "AAA = (BBB, CCC)",
- "BBB = (DDD, EEE)",
- "CCC = (ZZZ, GGG)",
- "DDD = (DDD, DDD)",
- "EEE = (EEE, EEE)",
- "GGG = (GGG, GGG)",
- "ZZZ = (ZZZ, ZZZ)",
- ];
- const tests_longer = [
- "LLR",
- "",
- "AAA = (BBB, BBB)",
- "BBB = (AAA, ZZZ)",
- "ZZZ = (ZZZ, ZZZ)",
- ];
- const START_NODE: keyof MapNodeTree = "AAA";
- const END_NODE: keyof MapNodeTree = "ZZZ";
- const input = await LoadInput(8);
- const [directions, map] = ParseMap(input);
- let nodeID: keyof MapNodeTree|undefined = START_NODE;
- let stepsTaken = 0;
- while (nodeID = GetNextNodeInMap(directions, map, nodeID, stepsTaken)) {
- stepsTaken++;
- if (nodeID == END_NODE) {
- break;
- }
- }
- console.log(`A total of ${stepsTaken} steps were taken`);
- /**
- * 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
- */
- 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
- */
- 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
- */
- 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,
- },
- };
|