Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a7dec2e

Browse files
Merge pull request knaxus#101 from TheSTL/master
--update : path change of A* algo
2 parents 5fc4d9d + d0aaeac commit a7dec2e

File tree

2 files changed

+217
-3
lines changed

2 files changed

+217
-3
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,9 @@ Collection of interview questions with Unit Tests. Problems includes Data Struct
8484
### Algorithms
8585

8686
- [LRU Cache](src/_Algorithms_/lru-cache)
87+
- Path Finders
88+
- [A*](src/_Algorithms_/path-finder/a-star)
8789

88-
### Path Finder
89-
90-
- [A\*](src/PathFinder/AStart)
9190

9291
### Classics
9392

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/**
2+
* h is calculate by Euclidean Distance.
3+
* Complexity can be imporved by using Min-heap.
4+
* Worse case time complexity is O(E), where E is the number of edges in the graph.
5+
* Read more: [http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html]
6+
*/
7+
function AStar(s, e, row, col, inputGrid) {
8+
const Row = row;
9+
const Col = col;
10+
const start = s;
11+
const end = e;
12+
13+
function cell() {
14+
this.cellValue = null;
15+
this.parent_i = -1;
16+
this.parent_j = -1;
17+
this.h = Number.MAX_SAFE_INTEGER;
18+
this.g = Number.MAX_SAFE_INTEGER;
19+
this.f = Number.MAX_SAFE_INTEGER;
20+
}
21+
22+
function pair(i, j, f) {
23+
this.i = i;
24+
this.j = j;
25+
this.f = f;
26+
}
27+
28+
const grid = [];
29+
30+
for (let i = 0; i < Row; i += 1) {
31+
grid[i] = [];
32+
for (let j = 0; j < Col; j += 1) {
33+
grid[i][j] = new cell();
34+
grid[i][j].cellValue = inputGrid[i][j];
35+
}
36+
}
37+
38+
39+
const isValid = (i, j) => i >= 0 && j >= 0 && i < Row && j < Col;
40+
41+
const isDestination = (i, j) => end.i === i && end.j === j;
42+
43+
const isBlocked = (i, j) => grid[i][j].cellValue === 0;
44+
45+
const euclideanDistance = (i, j) => Math.abs(i - end.i) * Math.abs(i - end.i)
46+
+ Math.abs(j - end.j) * Math.abs(j - end.j);
47+
48+
const trace = () => {
49+
const endRow = end.i;
50+
const endCol = end.j;
51+
const startRow = start.i;
52+
const startCol = start.j;
53+
54+
let i = endRow;
55+
let j = endCol;
56+
const path = [];
57+
58+
while (!(i === startRow && j === startCol)) {
59+
path.push([i, j]);
60+
61+
const nextI = grid[i][j].parent_i;
62+
const nextJ = grid[i][j].parent_j;
63+
i = nextI;
64+
j = nextJ;
65+
}
66+
path.push([i, j]);
67+
68+
for (let i = 0; i < path.length; i += 1) {
69+
console.log(path[i]);
70+
}
71+
};
72+
73+
const neighbourExplorer = (i, j, parentI, parentJ, openList, openListMap,
74+
closedListMap, distanceFromParent) => {
75+
if (!isValid(i, j)) {
76+
return false;
77+
}
78+
79+
if (isBlocked(i, j)) {
80+
return false;
81+
}
82+
83+
if (isDestination(i, j)) {
84+
grid[i][j].parent_i = parentI;
85+
grid[i][j].parent_j = parentJ;
86+
trace();
87+
return true;
88+
}
89+
90+
91+
const g = grid[parentI][parentJ].g + distanceFromParent;
92+
const h = euclideanDistance(i, j);
93+
const f = g + h;
94+
95+
if ((openListMap[[i, j]] && openListMap[[i, j]] > f)
96+
|| (closedListMap[[i, j]] && closedListMap[[i, j]] > f)
97+
|| (!closedListMap[[i, j]] && !openListMap[[i, j]])) {
98+
openListMap[[i, j]] = f;
99+
grid[i][j].parent_i = parentI;
100+
grid[i][j].parent_j = parentJ;
101+
grid[i][j].g = g;
102+
grid[i][j].h = h;
103+
grid[i][j].f = g + h;
104+
105+
const item = new pair(i, j, f);
106+
// can be improved by using Min-Heap DataStructure
107+
if (!openList.length) {
108+
openList.push(item);
109+
}
110+
let k = 0;
111+
let temp = item;
112+
for (; k < openList.length; k += 1) {
113+
if (openList[k].f > item.f) {
114+
[temp, openList[k]] = [openList[k], temp];
115+
}
116+
}
117+
openList[k] = temp;
118+
}
119+
return false;
120+
};
121+
122+
const search = () => {
123+
if (!isValid(start.i, start.j) || !isValid(end.i, end.j)) {
124+
return false;
125+
}
126+
127+
let i = start.i;
128+
let j = start.j;
129+
const openList = [];
130+
const openListMap = new Map();
131+
const closedListMap = new Map();
132+
let foundDest = false;
133+
134+
// Initialize start point
135+
grid[i][j].h = 0;
136+
grid[i][j].g = 0;
137+
grid[i][j].f = 0;
138+
139+
openList.push(new pair(i, j, 0.0));
140+
141+
openListMap[[i, j]] = 0;
142+
143+
while (openList.length > 0) {
144+
const currentCell = openList.shift();
145+
i = currentCell.i;
146+
j = currentCell.j;
147+
const currentF = currentCell.f;
148+
closedListMap[[i, j]] = currentF;
149+
const parentI = i;
150+
const parentJ = j;
151+
152+
foundDest = neighbourExplorer(i - 1, j, parentI, parentJ, openList, openListMap, closedListMap, 1); // for North
153+
if (foundDest) { break; }
154+
foundDest = neighbourExplorer(i, j - 1, parentI, parentJ, openList, openListMap, closedListMap, 1); // for West
155+
if (foundDest) { break; }
156+
foundDest = neighbourExplorer(i + 1, j, parentI, parentJ, openList, openListMap, closedListMap, 1); // for South
157+
if (foundDest) { break; }
158+
foundDest = neighbourExplorer(i, j + 1, parentI, parentJ, openList, openListMap, closedListMap, 1); // for East
159+
if (foundDest) { break; }
160+
foundDest = neighbourExplorer(i - 1, j - 1, parentI, parentJ, openList, openListMap, closedListMap, 1); // for N.W
161+
if (foundDest) { break; }
162+
foundDest = neighbourExplorer(i - 1, j + 1, parentI, parentJ, openList, openListMap, closedListMap, 1);// for S.W
163+
if (foundDest) { break; }
164+
foundDest = neighbourExplorer(i + 1, j + 1, parentI, parentJ, openList, openListMap, closedListMap, 1);// for S.E
165+
if (foundDest) { break; }
166+
foundDest = neighbourExplorer(i + 1, j - 1, parentI, parentJ, openList, openListMap, closedListMap, 1);// for N.E
167+
if (foundDest) { break; }
168+
}
169+
170+
171+
if (!foundDest) {
172+
return false;
173+
}
174+
return true;
175+
};
176+
search();
177+
}
178+
179+
180+
// const inputGrid = [
181+
// [1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
182+
// [1, 1, 1, 0, 1, 1, 1, 0, 1, 1],
183+
// [1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
184+
// [0, 0, 1, 0, 1, 0, 0, 0, 0, 1],
185+
// [1, 1, 1, 0, 1, 1, 1, 0, 1, 0],
186+
// [1, 0, 1, 1, 1, 1, 0, 1, 0, 0],
187+
// [1, 0, 0, 0, 0, 1, 0, 0, 0, 1],
188+
// [1, 0, 1, 1, 1, 1, 0, 1, 1, 1],
189+
// [1, 1, 1, 0, 0, 0, 1, 0, 0, 1],
190+
// ];
191+
192+
const inputGrid = [
193+
[1, 0, 0, 0, 0, 0],
194+
[1, 1, 1, 1, 1, 1],
195+
[1, 0, 0, 0, 0, 0],
196+
[1, 1, 1, 1, 1, 1],
197+
];
198+
199+
const ROW = inputGrid.length;
200+
const COL = inputGrid[0].length;
201+
const start = {
202+
i: 0,
203+
j: 0,
204+
};
205+
const end = {
206+
i: 3,
207+
j: 5,
208+
};
209+
210+
AStar(start, end, ROW, COL, inputGrid);
211+
212+
213+
module.exports = {
214+
AStar,
215+
};

0 commit comments

Comments
(0)

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /