lgrthms
Version:
Algorithms and data structures for your JavaScript and TypeScript projects 🧑💻
73 lines (72 loc) • 2.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.aStarAlgorithm = void 0;
const MinHeap_1 = require("../../dataStructures/MinHeap");
const MOVES = [[-1, 0], [0, 1], [0, -1], [1, 0]];
const OBSTACLE_VALUE = 1;
// O(wh * log(wh)) time | O(wh) space — where
// w is the width of the matrix
// h is the height of the matrix
function aStarAlgorithm(start, finish, matrix) {
const pointInfos = {};
const pointInfosHeap = new MinHeap_1.MinHeap((a, b) => a.priority - b.priority);
if (!isValidPointAndNotObstacle(start, matrix) || !isValidPointAndNotObstacle(finish, matrix)) {
return getResultantPath(finish, pointInfos);
}
const startInfo = { point: start, prev: null, distance: 0, priority: 0 };
pointInfos[getKey(start)] = startInfo;
pointInfosHeap.insert(startInfo);
while (pointInfosHeap.size > 0) {
const pointInfo = pointInfosHeap.extract();
const point = pointInfo.point;
if (point.row === finish.row && point.col === finish.col) {
break;
}
for (const move of MOVES) {
const neighbor = getPoint(point.row + move[0], point.col + move[1]);
if (!isValidPointAndNotObstacle(neighbor, matrix)) {
continue;
}
const key = getKey(neighbor);
const distance = pointInfo.distance + 1;
if (pointInfos[key] && distance >= pointInfos[key].distance) {
continue;
}
const priority = distance + manhattanDistance(neighbor, finish);
const neighborInfo = { point: neighbor, prev: point, distance, priority };
pointInfos[key] = neighborInfo;
pointInfosHeap.insert(neighborInfo);
}
}
return getResultantPath(finish, pointInfos);
}
exports.aStarAlgorithm = aStarAlgorithm;
function isValidPointAndNotObstacle(point, matrix) {
const isRowInBound = point.row >= 0 && point.row < matrix.length;
const isColInBound = point.col >= 0 && point.col < matrix[0].length;
return isRowInBound && isColInBound && matrix[point.row][point.col] !== OBSTACLE_VALUE;
}
function getResultantPath(finish, pointInfos) {
const resultantPath = { path: [], distance: -1 };
const finishKey = getKey(finish);
if (pointInfos[finishKey] === undefined) {
return resultantPath;
}
resultantPath.distance = pointInfos[finishKey].distance;
let current = finish;
while (current) {
resultantPath.path.push(current);
current = pointInfos[getKey(current)].prev;
}
resultantPath.path.reverse();
return resultantPath;
}
function manhattanDistance(current, finish) {
return Math.abs(current.row - finish.row) + Math.abs(current.col - finish.col);
}
function getPoint(row, col) {
return { row, col };
}
function getKey(point) {
return `${point.row}_${point.col}`;
}