UNPKG

lgrthms

Version:

Algorithms and data structures for your JavaScript and TypeScript projects 🧑‍💻

73 lines (72 loc) 2.9 kB
"use strict"; 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}`; }