Skip to content

Commit 24d3b4a

Browse files
committed
New algorithms + visualizers
1 parent c59b582 commit 24d3b4a

16 files changed

+812
-0
lines changed

Graphs/sample-graph.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"A": ["B", "C"],
3+
"B": ["A", "D", "E"],
4+
"C": ["A", "F"],
5+
"D": ["B"],
6+
"E": ["B", "F"],
7+
"F": ["C", "E"]
8+
}

Pathfinding/a-star.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Algorithm: A* Search
2+
// Type: Graph, Pathfinding, Heuristic-based Search
3+
// Time Complexity: O(E) or O(V log V) with priority queue
4+
// Space Complexity: O(V)
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <math.h>
9+
#include <limits.h>
10+
11+
#define N 5 // Grid size
12+
#define INF 1000000
13+
14+
typedef struct {
15+
int x, y;
16+
} Point;
17+
18+
typedef struct {
19+
int f, g, h;
20+
Point parent;
21+
int visited;
22+
} Node;
23+
24+
int dx[] = {-1, 1, 0, 0};
25+
int dy[] = {0, 0, -1, 1};
26+
27+
// Heuristic: Manhattan distance
28+
int heuristic(Point a, Point b) {
29+
return abs(a.x - b.x) + abs(a.y - b.y);
30+
}
31+
32+
// Check if position is inside grid and not blocked
33+
int isValid(int grid[N][N], int x, int y) {
34+
return x >= 0 && x < N && y >= 0 && y < N && grid[x][y] == 0;
35+
}
36+
37+
// A* algorithm on grid
38+
void aStar(int grid[N][N], Point start, Point goal) {
39+
Node nodes[N][N];
40+
41+
for (int i = 0; i < N; ++i)
42+
for (int j = 0; j < N; ++j) {
43+
nodes[i][j].f = INF;
44+
nodes[i][j].g = INF;
45+
nodes[i][j].h = 0;
46+
nodes[i][j].visited = 0;
47+
nodes[i][j].parent = (Point){-1, -1};
48+
}
49+
50+
nodes[start.x][start.y].g = 0;
51+
nodes[start.x][start.y].h = heuristic(start, goal);
52+
nodes[start.x][start.y].f = nodes[start.x][start.y].h;
53+
54+
while (1) {
55+
int minF = INF;
56+
Point current = {-1, -1};
57+
58+
// Find node with lowest f
59+
for (int i = 0; i < N; ++i)
60+
for (int j = 0; j < N; ++j)
61+
if (!nodes[i][j].visited && nodes[i][j].f < minF) {
62+
minF = nodes[i][j].f;
63+
current = (Point){i, j};
64+
}
65+
66+
if (current.x == -1) {
67+
printf("No path found\n");
68+
return;
69+
}
70+
71+
if (current.x == goal.x && current.y == goal.y) {
72+
// Reconstruct path
73+
printf("Path: ");
74+
Point p = goal;
75+
while (!(p.x == start.x && p.y == start.y)) {
76+
printf("(%d,%d) <- ", p.x, p.y);
77+
p = nodes[p.x][p.y].parent;
78+
}
79+
printf("(%d,%d)\n", start.x, start.y);
80+
return;
81+
}
82+
83+
nodes[current.x][current.y].visited = 1;
84+
85+
// Explore neighbors
86+
for (int d = 0; d < 4; ++d) {
87+
int nx = current.x + dx[d];
88+
int ny = current.y + dy[d];
89+
90+
if (!isValid(grid, nx, ny) || nodes[nx][ny].visited) continue;
91+
92+
int tentativeG = nodes[current.x][current.y].g + 1;
93+
94+
if (tentativeG < nodes[nx][ny].g) {
95+
nodes[nx][ny].parent = current;
96+
nodes[nx][ny].g = tentativeG;
97+
nodes[nx][ny].h = heuristic((Point){nx, ny}, goal);
98+
nodes[nx][ny].f = tentativeG + nodes[nx][ny].h;
99+
}
100+
}
101+
}
102+
}
103+
104+
// Example usage
105+
int main() {
106+
int grid[N][N] = {
107+
{0, 1, 0, 0, 0},
108+
{0, 1, 0, 1, 0},
109+
{0, 0, 0, 1, 0},
110+
{1, 1, 0, 0, 0},
111+
{0, 0, 0, 1, 0}
112+
};
113+
114+
Point start = {0, 0};
115+
Point goal = {4, 4};
116+
117+
aStar(grid, start, goal);
118+
return 0;
119+
}

Pathfinding/a-star.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Algorithm: A* Search
2+
// Type: Graph, Pathfinding, Heuristic-based Search
3+
// Time Complexity: O(E)
4+
// Space Complexity: O(V)
5+
6+
import java.util.*;
7+
8+
public class AStar {
9+
static class Node {
10+
String name;
11+
double f, g;
12+
13+
Node(String name, double g, double f) {
14+
this.name = name; this.g = g; this.f = f;
15+
}
16+
}
17+
18+
public static List<String> aStar(Map<String, List<Map.Entry<String, Integer>>> graph,
19+
String start, String goal,
20+
Map<String, Integer> heuristic) {
21+
PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparingDouble(n -> n.f));
22+
Map<String, String> cameFrom = new HashMap<>();
23+
Map<String, Double> gScore = new HashMap<>();
24+
25+
open.add(new Node(start, 0, heuristic.get(start)));
26+
gScore.put(start, 0.0);
27+
28+
while (!open.isEmpty()) {
29+
Node current = open.poll();
30+
31+
if (current.name.equals(goal)) {
32+
LinkedList<String> path = new LinkedList<>();
33+
while (cameFrom.containsKey(current.name)) {
34+
path.addFirst(current.name);
35+
current.name = cameFrom.get(current.name);
36+
}
37+
path.addFirst(start);
38+
return path;
39+
}
40+
41+
for (Map.Entry<String, Integer> neighbor : graph.get(current.name)) {
42+
double tentative_g = gScore.get(current.name) + neighbor.getValue();
43+
if (tentative_g < gScore.getOrDefault(neighbor.getKey(), Double.MAX_VALUE)) {
44+
cameFrom.put(neighbor.getKey(), current.name);
45+
gScore.put(neighbor.getKey(), tentative_g);
46+
double f = tentative_g + heuristic.get(neighbor.getKey());
47+
open.add(new Node(neighbor.getKey(), tentative_g, f));
48+
}
49+
}
50+
}
51+
return null;
52+
}
53+
}

Pathfinding/a-star.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Algorithm: A* Search
2+
// Type: Graph, Pathfinding, Heuristic-based Search
3+
// Time Complexity: O(E)
4+
// Space Complexity: O(V)
5+
6+
function aStar(start, goal, graph, heuristic) {
7+
const openSet = [[0, start]];
8+
const cameFrom = {};
9+
const gScore = { [start]: 0 };
10+
const fScore = { [start]: heuristic(start, goal) };
11+
12+
while (openSet.length > 0) {
13+
openSet.sort((a, b) => a[0] - b[0]);
14+
const [_, current] = openSet.shift();
15+
16+
if (current === goal) {
17+
const path = [];
18+
let node = current;
19+
while (cameFrom[node]) {
20+
path.unshift(node);
21+
node = cameFrom[node];
22+
}
23+
return [start, ...path];
24+
}
25+
26+
for (const [neighbor, cost] of graph[current]) {
27+
const tentative_g = gScore[current] + cost;
28+
if (!(neighbor in gScore) || tentative_g < gScore[neighbor]) {
29+
cameFrom[neighbor] = current;
30+
gScore[neighbor] = tentative_g;
31+
fScore[neighbor] = tentative_g + heuristic(neighbor, goal);
32+
openSet.push([fScore[neighbor], neighbor]);
33+
}
34+
}
35+
}
36+
37+
return null;
38+
}

Pathfinding/a-star.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Algorithm: A* Search
2+
# Type: Graph, Pathfinding, Heuristic-based Search
3+
# Time Complexity: O(E)
4+
# Space Complexity: O(V)
5+
6+
import heapq
7+
8+
def a_star(start, goal, graph, heuristic):
9+
open_set = [(0, start)]
10+
came_from = {}
11+
g_score = {start: 0}
12+
f_score = {start: heuristic(start, goal)}
13+
14+
while open_set:
15+
_, current = heapq.heappop(open_set)
16+
17+
if current == goal:
18+
path = []
19+
while current in came_from:
20+
path.append(current)
21+
current = came_from[current]
22+
return path[::-1] + [goal]
23+
24+
for neighbor, cost in graph[current]:
25+
tentative_g = g_score[current] + cost
26+
if neighbor not in g_score or tentative_g < g_score[neighbor]:
27+
came_from[neighbor] = current
28+
g_score[neighbor] = tentative_g
29+
f_score[neighbor] = tentative_g + heuristic(neighbor, goal)
30+
heapq.heappush(open_set, (f_score[neighbor], neighbor))
31+
32+
return None

Pathfinding/a-star.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Algorithm: A* Search
2+
// Type: Graph, Pathfinding, Heuristic-based Search
3+
// Time Complexity: O(E), worst-case exponential depending on heuristic
4+
// Space Complexity: O(V)
5+
6+
function AStar(start, goal, graph, heuristic):
7+
openSet = PriorityQueue()
8+
openSet.push(start, 0)
9+
cameFrom = empty map
10+
11+
gScore = map with default ∞
12+
gScore[start] = 0
13+
14+
fScore = map with default ∞
15+
fScore[start] = heuristic(start, goal)
16+
17+
while openSet is not empty:
18+
current = openSet.pop()
19+
20+
if current == goal:
21+
return reconstruct_path(cameFrom, current)
22+
23+
for each neighbor of current:
24+
tentative_gScore = gScore[current] + dist(current, neighbor)
25+
if tentative_gScore < gScore[neighbor]:
26+
cameFrom[neighbor] = current
27+
gScore[neighbor] = tentative_gScore
28+
fScore[neighbor] = gScore[neighbor] + heuristic(neighbor, goal)
29+
if neighbor not in openSet:
30+
openSet.push(neighbor, fScore[neighbor])
31+
32+
return failure
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Algorithm: RRT*
2+
// Type: Sampling-based Path Planning
3+
// Time: O(n log n), Space: O(n)
4+
5+
class Node {
6+
double x, y, cost;
7+
Node parent;
8+
9+
Node(double x, double y) {
10+
this.x = x; this.y = y; cost = 0;
11+
}
12+
}
13+
14+
double distance(Node a, Node b) {
15+
return Math.hypot(a.x - b.x, a.y - b.y);
16+
}
17+
18+
Node steer(Node from, Node to, double step) {
19+
double dist = distance(from, to);
20+
double theta = Math.atan2(to.y - from.y, to.x - from.x);
21+
return new Node(from.x + step * Math.cos(theta),
22+
from.y + step * Math.sin(theta));
23+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Algorithm: RRT*
2+
// Type: Sampling-based Path Planning
3+
// Time: O(n log n), Space: O(n)
4+
5+
class Node {
6+
constructor(x, y, cost = 0, parent = null) {
7+
this.x = x;
8+
this.y = y;
9+
this.cost = cost;
10+
this.parent = parent;
11+
}
12+
}
13+
14+
function distance(a, b) {
15+
return Math.hypot(a.x - b.x, a.y - b.y);
16+
}
17+
18+
function steer(from, to, step = 1.0) {
19+
const dist = distance(from, to);
20+
const theta = Math.atan2(to.y - from.y, to.x - from.x);
21+
return new Node(from.x + step * Math.cos(theta), from.y + step * Math.sin(theta), from.cost + step, from);
22+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Algorithm: RRT* (Rapidly-exploring Random Tree Star)
2+
# Type: Motion Planning, Sampling-based
3+
# Time Complexity: O(n log n)
4+
# Space Complexity: O(n)
5+
6+
import random
7+
import math
8+
9+
class Node:
10+
def __init__(self, x, y):
11+
self.x, self.y = x, y
12+
self.parent = None
13+
self.cost = 0
14+
15+
def distance(a, b):
16+
return math.hypot(a.x - b.x, a.y - b.y)
17+
18+
def steer(from_node, to_node, step=1.0):
19+
dist = distance(from_node, to_node)
20+
if dist < step:
21+
return Node(to_node.x, to_node.y)
22+
theta = math.atan2(to_node.y - from_node.y, to_node.x - from_node.x)
23+
return Node(from_node.x + step * math.cos(theta),
24+
from_node.y + step * math.sin(theta))
25+
26+
def rrt_star(start, goal, max_iter, map_bounds):
27+
tree = [start]
28+
for _ in range(max_iter):
29+
x_rand = Node(random.uniform(0, map_bounds[0]), random.uniform(0, map_bounds[1]))
30+
x_nearest = min(tree, key=lambda n: distance(n, x_rand))
31+
x_new = steer(x_nearest, x_rand)
32+
33+
if not is_obstacle(x_nearest, x_new):
34+
neighbors = [n for n in tree if distance(n, x_new) < 2.0]
35+
x_min = x_nearest
36+
c_min = x_nearest.cost + distance(x_nearest, x_new)
37+
38+
for n in neighbors:
39+
if not is_obstacle(n, x_new) and n.cost + distance(n, x_new) < c_min:
40+
x_min = n
41+
c_min = n.cost + distance(n, x_new)
42+
43+
x_new.parent = x_min
44+
x_new.cost = c_min
45+
tree.append(x_new)
46+
47+
for n in neighbors:
48+
if not is_obstacle(x_new, n) and x_new.cost + distance(x_new, n) < n.cost:
49+
n.parent = x_new
50+
n.cost = x_new.cost + distance(x_new, n)
51+
52+
return extract_path(goal)
53+
54+
# Dummy implementations
55+
def is_obstacle(a, b): return False
56+
def extract_path(goal): return []

0 commit comments

Comments
 (0)