Skip to content

Commit e81c04e

Browse files
committed
added A*
1 parent 3428308 commit e81c04e

File tree

4 files changed

+201
-2
lines changed

4 files changed

+201
-2
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ So far there are 6 segments
2020
- Recursion Tree
2121
- Turing Machine
2222

23-
I have implemented a total of `23 algorithms` so far. And will try to add more later.
23+
I have implemented a total of `24 algorithms` so far. And will try to add more later.
2424

2525
## Algorithms implemented
2626

2727
- DFS
2828
- BFS
2929
- Dijkstra
30+
- A star
3031
- Recursive Maze Creation
3132
- Bubble sort
3233
- Selection sort

src/algorithms/15puzzle.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
let flag;
3+
const inf = 1010
4+
let dir = "LRUD";
5+
let dx = [0,0,-1,1];
6+
let dy = [-1,1,0,0];
7+
let len = [0,0,0,0];
8+
let str = new Array(60);
9+
let ar = new Array(4);
10+
let idx = new Array(4);
11+
let transpose = new Array(4);
12+
13+
for (let i = 0; i < 4; i++) {
14+
ar[i] = new Array(4);
15+
idx[i] = new Array(4);
16+
transpose[i] = new Array(4);
17+
}
18+
19+
20+
export function isSolvable(){
21+
22+
}
23+
24+
function row_conflict(rc){
25+
let i, j, k, x, y, res = 0;
26+
27+
for (i = 0; i < 4; i++){
28+
x = (ar[rc][i] >> 2);
29+
if (ar[rc][i] != 16) idx[x][len[x]++] = ar[rc][i];
30+
}
31+
32+
for (i = 0; i < 4; i++){
33+
if (len[i] > 1){
34+
for (j = 0; j < len[i]; j++){
35+
for (k = j + 1; k < len[i]; k++){
36+
if (idx[i][j] > idx[i][k]) res += 2;
37+
}
38+
}
39+
}
40+
len[i] = 0;
41+
}
42+
return res;
43+
}
44+
45+
function column_conflict(rc){
46+
let i, j, k, x, y, res = 0;
47+
48+
for (i = 0; i < 4; i++){
49+
x = (ar[i][rc] & 3);
50+
if (ar[i][rc] != 16) idx[x][len[x]++] = ar[i][rc];
51+
}
52+
53+
for (i = 0; i < 4; i++){
54+
if (len[i] > 1){
55+
for (j = 0; j < len[i]; j++){
56+
for (k = j + 1; k < len[i]; k++){
57+
if (idx[i][j] > idx[i][k]) res += 2;
58+
}
59+
}
60+
}
61+
len[i] = 0;
62+
}
63+
return res;
64+
}
65+
66+
let heuristic(bx, by){
67+
let i, j, k, l, res, linear_conflict = 0, manhattan_distance = 0;
68+
69+
for (i = 0; i < 4; i++){
70+
for (j = 0; j < 4; j++){
71+
transpose[j][i] = ar[i][j];
72+
if (ar[i][j] != 16){
73+
manhattan_distance += F(i, j);
74+
}
75+
}
76+
linear_conflict += row_conflict(i);
77+
linear_conflict += column_conflict(i);
78+
}
79+
80+
res = manhattan_distance + linear_conflict;
81+
return res;
82+
}
83+
84+
function ida(bx, by, lx, ly, g, lim, d, h){
85+
if (flag) return 0;
86+
87+
if (!h){
88+
if (!flag){
89+
flag = true;
90+
str[d] = 0;
91+
//puts(str);
92+
console.log(str);
93+
}
94+
return g;
95+
}
96+
97+
let f = g + h;
98+
if (f > lim) return f;
99+
100+
let i, k, l, nh, r, res = inf;
101+
for (i = 0; i < 4; i++){
102+
k = bx + dx[i], l = by + dy[i];
103+
if (k >= 0 && k < 4 && l >= 0 && l < 4 && !(k === lx && l === ly)){
104+
nh = h;
105+
nh -= F(k, l);
106+
if (bx !== k) nh -= row_conflict(bx), nh -= row_conflict(k);
107+
if (by !== l) nh -= column_conflict(by), nh -= column_conflict(l);
108+
swap(ar[bx][by], ar[k][l]);
109+
let sw ;
110+
111+
nh += F(bx, by);
112+
if (bx != k) nh += row_conflict(bx), nh += row_conflict(k);
113+
if (by != l) nh += column_conflict(by), nh += column_conflict(l);
114+
115+
str[d] = dir[i];
116+
r = ida(k, l, bx, by, g + 1, lim, d + 1, nh);
117+
swap(ar[bx][by], ar[k][l]);
118+
if (r < res) res = r;
119+
if (r <= lim) return r;
120+
}
121+
}
122+
123+
return res;
124+
}
125+
126+
127+
*/

src/algorithms/Astar.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Performs Dijkstra's algorithm; returns *all* nodes in the order
2+
// in which they were visited. Also makes nodes point back to their
3+
// previous node, effectively allowing us to compute the shortest path
4+
// by backtracking from the finish node.
5+
export function aStar(grid, startNode, finishNode) {
6+
const visitedNodesInOrder = [];
7+
startNode.distance = 0;
8+
const unvisitedNodes = getAllNodes(grid);
9+
while (!!unvisitedNodes.length) {
10+
sortNodesByDistance(unvisitedNodes,finishNode);
11+
const closestNode = unvisitedNodes.shift();
12+
// If we encounter a wall, we skip it.
13+
if (closestNode.isWall) continue;
14+
// If the closest node is at a distance of infinity,
15+
// we must be trapped and should therefore stop.
16+
if (closestNode.distance === Infinity) return visitedNodesInOrder;
17+
closestNode.isVisited = true;
18+
visitedNodesInOrder.push(closestNode);
19+
if (closestNode === finishNode) return visitedNodesInOrder;
20+
updateUnvisitedNeighbors(closestNode, grid);
21+
}
22+
}
23+
24+
function sortNodesByDistance(unvisitedNodes,finishNode) {
25+
unvisitedNodes.sort((nodeA, nodeB) => (nodeA.distance+Math.abs(finishNode.row-nodeA.row)+Math.abs(finishNode.col-nodeA.col))
26+
- (nodeB.distance+Math.abs(finishNode.row-nodeB.row)+Math.abs(finishNode.col-nodeB.col)));
27+
}
28+
29+
function updateUnvisitedNeighbors(node, grid) {
30+
const unvisitedNeighbors = getUnvisitedNeighbors(node, grid);
31+
for (const neighbor of unvisitedNeighbors) {
32+
neighbor.distance = node.distance + 1;
33+
neighbor.previousNode = node;
34+
}
35+
}
36+
37+
function getUnvisitedNeighbors(node, grid) {
38+
const neighbors = [];
39+
const {col, row} = node;
40+
if (row > 0) neighbors.push(grid[row - 1][col]);
41+
if (row < grid.length - 1) neighbors.push(grid[row + 1][col]);
42+
if (col > 0) neighbors.push(grid[row][col - 1]);
43+
if (col < grid[0].length - 1) neighbors.push(grid[row][col + 1]);
44+
return neighbors.filter(neighbor => !neighbor.isVisited);
45+
}
46+
47+
function getAllNodes(grid) {
48+
const nodes = [];
49+
for (const row of grid) {
50+
for (const node of row) {
51+
nodes.push(node);
52+
}
53+
}
54+
return nodes;
55+
}
56+
57+
// Backtracks from the finishNode to find the shortest path.
58+
// Only works when called *after* the dijkstra method above.
59+
export function getNodesInShortestPathOrder(finishNode) {
60+
const nodesInShortestPathOrder = [];
61+
let currentNode = finishNode;
62+
while (currentNode !== null) {
63+
nodesInShortestPathOrder.unshift(currentNode);
64+
currentNode = currentNode.previousNode;
65+
}
66+
return nodesInShortestPathOrder;
67+
}

src/pathfinderComponents/pathfinder.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {dijkstra,getNodesInShortestPathOrder} from "../algorithms/dijkstra";
66
import {getMaze} from "../algorithms/recursiveMaze";
77
import {bfsdfs} from "../algorithms/bfs";
88
import {randomMaze} from "../algorithms/randomMaze";
9+
import {aStar} from "../algorithms/Astar";
910

1011
class Pathfinder extends Component {
1112
constructor() {
@@ -14,7 +15,7 @@ class Pathfinder extends Component {
1415
grid:[],
1516
mouseIsPressed:false,
1617
algorithms:[
17-
"Dijsktra","BFS","DFS"
18+
"Dijsktra","A star","BFS","DFS"
1819
],
1920
algo:0,
2021
mazes:[
@@ -160,6 +161,9 @@ class Pathfinder extends Component {
160161
visitedNodesInOrder = dijkstra(grid, startNode, finishNode);
161162
break;
162163
case 1:
164+
visitedNodesInOrder = aStar(grid, startNode, finishNode);
165+
break;
166+
case 2:
163167
visitedNodesInOrder = bfsdfs(grid, startNode, finishNode,"bfs");
164168
break;
165169
default:

0 commit comments

Comments
 (0)