UNPKG

algs4js

Version:

Basic algorithms and data structures implemented with es6

195 lines (167 loc) 6.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** Class to find shortest path This class uses a Breadth First Search (BFS) algorithm to find the shortest path. @class */ var KnightShortestPath = function () { /** @constructor */ function KnightShortestPath(boardSize) { _classCallCheck(this, KnightShortestPath); // The number of squares per edge of the board square this.boardSize = boardSize; // The shortest path predecessor array this.predArr = []; // Board square markers so the engine knows if it already visited a square this.board = []; for (var row = 0; row < this.boardSize; row++) { this.board[row] = []; for (var col = 0; col < this.boardSize; col++) { this.board[row][col] = -1; } } } /** This function will use BFS to find the shortest path between two squares. The results are an array of move predecessor indices. The predecessor array is a MoveEngine property. @function @param {number} startIdx - The index of the starting square @param {number} endIdx - The index of the ending square @return {number} The number of moves in shortest path */ _createClass(KnightShortestPath, [{ key: "getShortestPath", value: function getShortestPath(startIdx, endIdx) { var _this = this; // Boiler plate operations this.startIdx = startIdx; this.endIdx = endIdx; var startPos = this.getRowColFromIdx(startIdx); var endPos = this.getRowColFromIdx(endIdx); // The DFS search queue var queue = []; // Initialize the starting square this.board[startPos.row][startPos.col] = 0; this.predArr[startIdx] = null; // Start search queue.push(startPos); var _loop = function _loop() { // Remove element from head of queue var pos = queue.shift(); // Check if reached the end position if (pos.row === endPos.row && pos.col === endPos.col) { return { v: _this.board[endPos.row][endPos.col] }; } // Get all neighboring moves var neighbors = _this.getValidNeighbors(pos.row, pos.col); neighbors.forEach(function (neighbor) { _this.board[neighbor.row][neighbor.col] = _this.board[pos.row][pos.col] + 1; _this.addPredecessor(neighbor, pos); queue.push(neighbor); }); }; while (queue.length > 0) { var _ret = _loop(); if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v; } return -1; } /** Function to convert from square index to row, column position @function @param {number} idx - The index of the square */ }, { key: "getRowColFromIdx", value: function getRowColFromIdx(idx) { var row = Math.floor(idx / this.boardSize); var col = idx % this.boardSize; return { row: row, col: col }; } /** Function to add the predecessor square index of a neighbor square to the predecessor array. @function @param (Object) neighbor - The neighbor row, column position @param {Object} predecessor- the predecessor row, column position */ }, { key: "addPredecessor", value: function addPredecessor(neighbor, predecessor) { var neighborIdx = this.boardSize * neighbor.row + neighbor.col; var predecessorIdx = this.boardSize * predecessor.row + predecessor.col; this.predArr[neighborIdx] = predecessorIdx; } /** Function to add a nieghboring move to and array of moves @function @param (Array) arr - The array of neighboring moves @param {number} row - the neighbor row position @param {number} col - the neighbor column position */ }, { key: "addValidNeighbor", value: function addValidNeighbor(arr, row, col) { if (row >= 0 && row < this.boardSize && col >= 0 && col < this.boardSize && this.board[row][col] === -1) { arr.push({ row: row, col: col }); } } /** Function to get all nieghboring moves from a square. It will validate and reject any squares already visited @function @param {number} row - the position row position @param {number} col - the position column position @return (Array) arr - The array of neighboring moves */ }, { key: "getValidNeighbors", value: function getValidNeighbors(row, col) { var arr = []; this.addValidNeighbor(arr, row + 2, col + 1); this.addValidNeighbor(arr, row + 1, col + 2); this.addValidNeighbor(arr, row - 1, col + 2); this.addValidNeighbor(arr, row - 2, col + 1); this.addValidNeighbor(arr, row - 2, col - 1); this.addValidNeighbor(arr, row - 1, col - 2); this.addValidNeighbor(arr, row + 1, col - 2); this.addValidNeighbor(arr, row + 2, col - 1); return arr; } /** Function that gets the array of indices visited during the shortest path moves. @return {Array} - The array of idices visited */ }, { key: "getMoveStack", value: function getMoveStack() { var moveStack = [this.endIdx]; for (var idx = this.endIdx; idx !== this.startIdx; idx = this.predArr[idx]) { if (this.predArr[idx] !== this.startIdx) { moveStack.unshift(this.predArr[idx]); } } return moveStack; } }]); return KnightShortestPath; }(); exports.default = KnightShortestPath;