mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-13 16:17:54 +00:00
Docs: Update benchmark results
This commit is contained in:
6
README
6
README
@@ -28,19 +28,19 @@ The list below shows the pass/fail status and execution time for each model on e
|
||||
|
||||
<!-- RESULTS_START -->
|
||||
**google/gemini-2.5-pro**
|
||||
- 1_dijkstra: ❌ Fail (0.036s)
|
||||
- 1_dijkstra: ❌ Fail (0.037s)
|
||||
- 2_convex_hull: ⚪ Not Run
|
||||
- 3_lis: ⚪ Not Run
|
||||
- 4_determinant: ⚪ Not Run
|
||||
|
||||
**anthropic/claude-sonnet-4.5**
|
||||
- 1_dijkstra: ❌ Fail (0.032s)
|
||||
- 1_dijkstra: ❌ Fail (0.035s)
|
||||
- 2_convex_hull: ⚪ Not Run
|
||||
- 3_lis: ⚪ Not Run
|
||||
- 4_determinant: ⚪ Not Run
|
||||
|
||||
**openai/gpt-5-codex**
|
||||
- 1_dijkstra: ❌ Fail (0.031s)
|
||||
- 1_dijkstra: ❌ Fail (0.033s)
|
||||
- 2_convex_hull: ⚪ Not Run
|
||||
- 3_lis: ⚪ Not Run
|
||||
- 4_determinant: ⚪ Not Run
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
async function findShortestPath(graph, start, end) {
|
||||
// Dynamically import the priority queue library from CDN
|
||||
const { default: PriorityQueue } = await import(
|
||||
'https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm'
|
||||
);
|
||||
|
||||
// Initialize distances object with Infinity for all nodes
|
||||
const distances = {};
|
||||
for (const node in graph) {
|
||||
distances[node] = Infinity;
|
||||
}
|
||||
distances[start] = 0;
|
||||
|
||||
// Initialize visited set
|
||||
const visited = new Set();
|
||||
|
||||
// Create a min-priority queue (lower distance = higher priority)
|
||||
const pq = new PriorityQueue({
|
||||
comparator: (a, b) => a.distance - b.distance
|
||||
});
|
||||
|
||||
// Add start node to priority queue
|
||||
pq.queue({ node: start, distance: 0 });
|
||||
|
||||
while (pq.length > 0) {
|
||||
const { node: currentNode, distance: currentDistance } = pq.dequeue();
|
||||
|
||||
// Skip if already visited
|
||||
if (visited.has(currentNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark as visited
|
||||
visited.add(currentNode);
|
||||
|
||||
// If we reached the end node, return the distance
|
||||
if (currentNode === end) {
|
||||
return currentDistance;
|
||||
}
|
||||
|
||||
// Skip if current distance is outdated
|
||||
if (currentDistance > distances[currentNode]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check all neighbors
|
||||
const neighbors = graph[currentNode] || {};
|
||||
for (const neighbor in neighbors) {
|
||||
if (visited.has(neighbor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const weight = neighbors[neighbor];
|
||||
const newDistance = currentDistance + weight;
|
||||
|
||||
// If we found a shorter path, update it
|
||||
if (newDistance < distances[neighbor]) {
|
||||
distances[neighbor] = newDistance;
|
||||
pq.queue({ node: neighbor, distance: newDistance });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, no path exists
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
(async () => {
|
||||
const graph = {
|
||||
'A': { 'B': 1, 'C': 4 },
|
||||
'B': { 'A': 1, 'C': 2, 'D': 5 },
|
||||
'C': { 'A': 4, 'B': 2, 'D': 1 },
|
||||
'D': { 'B': 5, 'C': 1 }
|
||||
};
|
||||
|
||||
const shortestPath = await findShortestPath(graph, 'A', 'D');
|
||||
console.log('Shortest path from A to D:', shortestPath); // Output: 4
|
||||
|
||||
const noPath = await findShortestPath(graph, 'A', 'E');
|
||||
console.log('Path from A to E (non-existent):', noPath); // Output: Infinity
|
||||
})();
|
||||
@@ -1,87 +0,0 @@
|
||||
async function findShortestPath(graph, start, end) {
|
||||
// Dynamically import the priority queue library from CDN
|
||||
const { default: PriorityQueue } = await import(
|
||||
'https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm'
|
||||
);
|
||||
|
||||
// Initialize distances map - all nodes start at Infinity except start node
|
||||
const distances = {};
|
||||
for (let node in graph) {
|
||||
distances[node] = Infinity;
|
||||
}
|
||||
distances[start] = 0;
|
||||
|
||||
// Create a min-heap priority queue (lower distance = higher priority)
|
||||
const pq = new PriorityQueue({
|
||||
comparator: (a, b) => a.distance - b.distance
|
||||
});
|
||||
|
||||
// Track visited nodes to avoid reprocessing
|
||||
const visited = new Set();
|
||||
|
||||
// Start with the initial node
|
||||
pq.queue({ node: start, distance: 0 });
|
||||
|
||||
while (pq.length > 0) {
|
||||
const { node: currentNode, distance: currentDistance } = pq.dequeue();
|
||||
|
||||
// Skip if already visited
|
||||
if (visited.has(currentNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark as visited
|
||||
visited.add(currentNode);
|
||||
|
||||
// If we reached the end node, return the distance
|
||||
if (currentNode === end) {
|
||||
return currentDistance;
|
||||
}
|
||||
|
||||
// Check if current node exists in graph
|
||||
if (!graph[currentNode]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Explore neighbors
|
||||
for (let neighbor in graph[currentNode]) {
|
||||
if (!visited.has(neighbor)) {
|
||||
const weight = graph[currentNode][neighbor];
|
||||
const newDistance = currentDistance + weight;
|
||||
|
||||
// If we found a shorter path, update it
|
||||
if (newDistance < distances[neighbor]) {
|
||||
distances[neighbor] = newDistance;
|
||||
pq.queue({ node: neighbor, distance: newDistance });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, no path exists to the end node
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
const graph = {
|
||||
'A': { 'B': 1, 'C': 4 },
|
||||
'B': { 'A': 1, 'C': 2, 'D': 5 },
|
||||
'C': { 'A': 4, 'B': 2, 'D': 1 },
|
||||
'D': { 'B': 5, 'C': 1 }
|
||||
};
|
||||
|
||||
findShortestPath(graph, 'A', 'D').then(distance => {
|
||||
console.log(`Shortest path from A to D: ${distance}`); // Output: 4 (A -> B -> C -> D)
|
||||
});
|
||||
|
||||
// Example with no path
|
||||
const disconnectedGraph = {
|
||||
'A': { 'B': 1 },
|
||||
'B': { 'A': 1 },
|
||||
'C': { 'D': 1 },
|
||||
'D': { 'C': 1 }
|
||||
};
|
||||
|
||||
findShortestPath(disconnectedGraph, 'A', 'D').then(distance => {
|
||||
console.log(`Shortest path from A to D: ${distance}`); // Output: Infinity
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
async function findShortestPath(graph, start, end) {
|
||||
const PriorityQueue = (await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm')).default;
|
||||
const distances = Object.keys(graph).reduce((acc, node) => ({ ...acc, [node]: Infinity }), {});
|
||||
distances[start] = 0;
|
||||
const pq = new PriorityQueue({ comparator: (a, b) => a.distance - b.distance });
|
||||
pq.queue({ node: start, distance: 0 });
|
||||
const visited = new Set();
|
||||
while (pq.length > 0) {
|
||||
const { node, distance } = pq.dequeue();
|
||||
if (visited.has(node)) continue;
|
||||
visited.add(node);
|
||||
if (node === end) return distance;
|
||||
for (const [neighbor, weight] of Object.entries(graph[node] || {})) {
|
||||
const newDistance = distance + weight;
|
||||
if (newDistance < distances[neighbor]) {
|
||||
distances[neighbor] = newDistance;
|
||||
pq.queue({ node: neighbor, distance: newDistance });
|
||||
}
|
||||
}
|
||||
}
|
||||
return distances[end];
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/**
|
||||
* Finds the shortest path in a weighted, undirected graph using Dijkstra's algorithm.
|
||||
*
|
||||
* This function dynamically imports the 'js-priority-queue' library to manage nodes to visit.
|
||||
*
|
||||
* @param {object} graph - The graph structure. e.g., { 'A': { 'B': 1, 'C': 4 }, 'B': { ... }, ... }
|
||||
* @param {string} startNode - The starting node.
|
||||
* @param {string} endNode - The ending node.
|
||||
* @returns {Promise<number>} The total weight of the shortest path, or Infinity if no path exists.
|
||||
*/
|
||||
async function findShortestPath(graph, startNode, endNode) {
|
||||
let PriorityQueue;
|
||||
try {
|
||||
// Dynamically import the PriorityQueue library from a CDN.
|
||||
// The { default: ... } syntax is used to get the default export from the UMD module.
|
||||
const PQLib = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/priority-queue.min.js');
|
||||
PriorityQueue = PQLib.default;
|
||||
} catch (e) {
|
||||
console.error("Failed to load the Priority Queue library from the CDN.", e);
|
||||
// Can't proceed without the library.
|
||||
throw new Error("Could not load a required dependency.");
|
||||
}
|
||||
|
||||
// 1. Initialize distances, priority queue, and previous nodes map
|
||||
const distances = {};
|
||||
const priorityQueue = new PriorityQueue({
|
||||
// The comparator ensures the queue is a min-priority queue based on distance.
|
||||
comparator: (a, b) => a.distance - b.distance
|
||||
});
|
||||
|
||||
// Set initial distances for all nodes
|
||||
for (const node in graph) {
|
||||
if (node === startNode) {
|
||||
distances[node] = 0;
|
||||
priorityQueue.queue({ node: node, distance: 0 });
|
||||
} else {
|
||||
distances[node] = Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
// If the start or end node is not in the graph, no path can exist.
|
||||
if (distances[startNode] === undefined || distances[endNode] === undefined) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
|
||||
// 2. Main loop of Dijkstra's algorithm
|
||||
while (priorityQueue.length > 0) {
|
||||
// Get the node with the smallest distance from the queue
|
||||
const { node: currentNode, distance: currentDistance } = priorityQueue.dequeue();
|
||||
|
||||
// If we've already found a shorter path to the current node, skip it.
|
||||
if (currentDistance > distances[currentNode]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we've reached the end node, we have found the shortest path.
|
||||
if (currentNode === endNode) {
|
||||
// The value in 'distances' is the shortest path weight.
|
||||
return distances[endNode];
|
||||
}
|
||||
|
||||
const neighbors = graph[currentNode];
|
||||
if (!neighbors) continue; // Skip if node has no outgoing edges
|
||||
|
||||
// 3. Relaxation step: Check all neighbors of the current node
|
||||
for (const neighbor in neighbors) {
|
||||
const weight = neighbors[neighbor];
|
||||
const distanceThroughCurrent = currentDistance + weight;
|
||||
|
||||
// If we found a shorter path to the neighbor, update it.
|
||||
if (distanceThroughCurrent < distances[neighbor]) {
|
||||
distances[neighbor] = distanceThroughCurrent;
|
||||
// Enqueue the neighbor with its new, shorter distance.
|
||||
priorityQueue.queue({ node: neighbor, distance: distanceThroughCurrent });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. If the loop finishes and we haven't returned, the end node is unreachable.
|
||||
return distances[endNode]; // This will be Infinity
|
||||
}
|
||||
|
||||
|
||||
// --- Example Usage ---
|
||||
|
||||
// Define the graph structure
|
||||
const graph = {
|
||||
'A': { 'B': 2, 'C': 5 },
|
||||
'B': { 'A': 2, 'C': 6, 'D': 1 },
|
||||
'C': { 'A': 5, 'B': 6, 'D': 6, 'E': 8 },
|
||||
'D': { 'B': 1, 'C': 6, 'E': 2 },
|
||||
'E': { 'C': 8, 'D': 2 },
|
||||
'F': { 'G': 1 }, // A disconnected part of the graph
|
||||
'G': { 'F': 1 }
|
||||
};
|
||||
|
||||
// We wrap the calls in an async IIFE (Immediately Invoked Function Expression)
|
||||
// because we can only use 'await' inside an async function.
|
||||
(async () => {
|
||||
console.log("Finding shortest path from A to E...");
|
||||
const pathAtoE = await findShortestPath(graph, 'A', 'E');
|
||||
console.log(`Shortest path from A to E has a weight of: ${pathAtoE}`); // Expected: 5 (A -> B -> D -> E)
|
||||
|
||||
console.log("\nFinding shortest path from A to C...");
|
||||
const pathAtoC = await findShortestPath(graph, 'A', 'C');
|
||||
console.log(`Shortest path from A to C has a weight of: ${pathAtoC}`); // Expected: 5 (A -> C)
|
||||
|
||||
console.log("\nFinding shortest path from A to A...");
|
||||
const pathAtoA = await findShortestPath(graph, 'A', 'A');
|
||||
console.log(`Shortest path from A to A has a weight of: ${pathAtoA}`); // Expected: 0
|
||||
|
||||
console.log("\nFinding shortest path from A to F (unreachable)...");
|
||||
const pathAtoF = await findShortestPath(graph, 'A', 'F');
|
||||
console.log(`Shortest path from A to F has a weight of: ${pathAtoF}`); // Expected: Infinity
|
||||
|
||||
console.log("\nFinding shortest path from A to Z (non-existent node)...");
|
||||
const pathAtoZ = await findShortestPath(graph, 'A', 'Z');
|
||||
console.log(`Shortest path from A to Z has a weight of: ${pathAtoZ}`); // Expected: Infinity
|
||||
})();
|
||||
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* Finds the shortest path in a weighted, undirected graph using Dijkstra's algorithm.
|
||||
* This function dynamically imports a Priority Queue library from a CDN.
|
||||
*
|
||||
* @param {object} graph - The graph structure, e.g., { 'A': { 'B': 1, 'C': 4 }, 'B': { ... } }.
|
||||
* @param {string} startNode - The starting node for the path.
|
||||
* @param {string} endNode - The destination node for the path.
|
||||
* @returns {Promise<number>} A promise that resolves to the total weight of the shortest path, or Infinity if no path exists.
|
||||
*/
|
||||
async function findShortestPath(graph, startNode, endNode) {
|
||||
// 1. Dynamically import the priority queue library from a CDN.
|
||||
// The 'js-priority-queue' library is a UMD module, so the main export
|
||||
// is often on the 'default' property when imported this way.
|
||||
let PriorityQueue;
|
||||
try {
|
||||
const PriorityQueueModule = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/priority-queue.min.js');
|
||||
PriorityQueue = PriorityQueueModule.default;
|
||||
} catch (error) {
|
||||
console.error("Failed to load the Priority Queue library:", error);
|
||||
// Cannot proceed without the library, so we throw an error.
|
||||
throw new Error("Could not load a required dependency.");
|
||||
}
|
||||
|
||||
|
||||
// 2. Initialize data structures for Dijkstra's algorithm.
|
||||
const distances = {}; // Stores the shortest known distance from the startNode to every other node.
|
||||
const previous = {}; // Stores the preceding node in the shortest path.
|
||||
|
||||
// A min-priority queue to store nodes to visit, prioritized by distance.
|
||||
const pq = new PriorityQueue({ comparator: (a, b) => a.priority - b.priority });
|
||||
|
||||
// 3. Set initial state.
|
||||
Object.keys(graph).forEach(node => {
|
||||
if (node === startNode) {
|
||||
distances[node] = 0;
|
||||
pq.queue({ value: node, priority: 0 }); // Add the start node to the queue with priority 0.
|
||||
} else {
|
||||
distances[node] = Infinity;
|
||||
}
|
||||
previous[node] = null;
|
||||
});
|
||||
|
||||
// 4. Main loop of the algorithm.
|
||||
while (pq.length > 0) {
|
||||
// Get the node with the smallest distance from the queue.
|
||||
const { value: currentNode } = pq.dequeue();
|
||||
|
||||
// If we've reached the end node, we have found the shortest path.
|
||||
if (currentNode === endNode) {
|
||||
// If a path exists, the distance will be a finite number.
|
||||
if (distances[endNode] !== Infinity) {
|
||||
return distances[endNode];
|
||||
}
|
||||
// This break is for the case where endNode is unreachable but was queued
|
||||
// with an infinite priority (which shouldn't happen with this logic, but is safe).
|
||||
break;
|
||||
}
|
||||
|
||||
// Explore neighbors of the current node.
|
||||
if (graph[currentNode]) {
|
||||
for (const neighbor in graph[currentNode]) {
|
||||
const weight = graph[currentNode][neighbor];
|
||||
const newPathWeight = distances[currentNode] + weight;
|
||||
|
||||
// If we've found a shorter path to this neighbor...
|
||||
if (newPathWeight < distances[neighbor]) {
|
||||
// ...update its distance, record the path, and add it to the queue.
|
||||
distances[neighbor] = newPathWeight;
|
||||
previous[neighbor] = currentNode;
|
||||
pq.queue({ value: neighbor, priority: newPathWeight });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. If the loop finishes and we haven't returned, the endNode was not reachable.
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
|
||||
// --- Example Usage ---
|
||||
|
||||
// Define our weighted, undirected graph.
|
||||
const graph = {
|
||||
'A': { 'B': 1, 'C': 4 },
|
||||
'B': { 'A': 1, 'C': 2, 'D': 5 },
|
||||
'C': { 'A': 4, 'B': 2, 'E': 3 },
|
||||
'D': { 'B': 5, 'E': 1 },
|
||||
'E': { 'C': 3, 'D': 1 },
|
||||
'F': { 'G': 1 }, // An unconnected component
|
||||
'G': { 'F': 1 }
|
||||
};
|
||||
|
||||
// We use an async IIFE (Immediately Invoked Function Expression) to run our async function.
|
||||
(async () => {
|
||||
try {
|
||||
console.log("Finding shortest path from A to E...");
|
||||
const pathWeight1 = await findShortestPath(graph, 'A', 'E');
|
||||
// Expected Path: A -> B -> C -> E, Weight: 1 + 2 + 3 = 6
|
||||
console.log(`Shortest path weight from A to E is: ${pathWeight1}`); // Output: 6
|
||||
|
||||
console.log("\nFinding shortest path from A to D...");
|
||||
const pathWeight2 = await findShortestPath(graph, 'A', 'D');
|
||||
// Expected Path: A -> B -> D, Weight: 1 + 5 = 6
|
||||
console.log(`Shortest path weight from A to D is: ${pathWeight2}`); // Output: 6
|
||||
|
||||
console.log("\nFinding shortest path from A to A...");
|
||||
const pathWeight3 = await findShortestPath(graph, 'A', 'A');
|
||||
console.log(`Shortest path weight from A to A is: ${pathWeight3}`); // Output: 0
|
||||
|
||||
console.log("\nFinding shortest path from A to F (unreachable)...");
|
||||
const pathWeight4 = await findShortestPath(graph, 'A', 'F');
|
||||
console.log(`Shortest path weight from A to F is: ${pathWeight4}`); // Output: Infinity
|
||||
} catch(err) {
|
||||
console.error("An error occurred during pathfinding:", err);
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1 @@
|
||||
const findShortestPath = async (graph, startNode, endNode) => { const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/priority-queue.min.js'); const distances = Object.keys(graph).reduce((acc, node) => (acc[node] = Infinity, acc), {}); const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] }); distances[startNode] = 0; pq.queue([startNode, 0]); while (pq.length) { const [currentNode, currentDist] = pq.dequeue(); if (currentDist > distances[currentNode]) continue; if (currentNode === endNode) return currentDist; for (const neighbor in graph[currentNode] || {}) { const newDist = currentDist + graph[currentNode][neighbor]; if (newDist < distances[neighbor]) { distances[neighbor] = newDist; pq.queue([neighbor, newDist]); } } } return distances[endNode]; };
|
||||
@@ -1,71 +0,0 @@
|
||||
// Lazy-load the PriorityQueue module once and cache the Promise
|
||||
let priorityQueueModulePromise;
|
||||
|
||||
/**
|
||||
* Asynchronously finds the total weight of the shortest path between two nodes
|
||||
* in a weighted, undirected graph using Dijkstra's algorithm.
|
||||
*
|
||||
* @param {Object<string, Object<string, number>>} graph - Adjacency list representation of the graph.
|
||||
* @param {string} start - The starting node.
|
||||
* @param {string} end - The destination node.
|
||||
* @returns {Promise<number>} Total weight of the shortest path or Infinity if no path exists.
|
||||
*/
|
||||
export async function findShortestPath(graph, start, end) {
|
||||
if (!graph || graph[start] === undefined || graph[end] === undefined) {
|
||||
return Infinity;
|
||||
}
|
||||
if (start === end) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Dynamically import js-priority-queue from a CDN (via jsDelivr +esm build)
|
||||
if (!priorityQueueModulePromise) {
|
||||
priorityQueueModulePromise = import(
|
||||
'https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm'
|
||||
);
|
||||
}
|
||||
|
||||
const { default: PriorityQueue } = await priorityQueueModulePromise;
|
||||
|
||||
const distances = Object.create(null);
|
||||
const visited = new Set();
|
||||
|
||||
// Initialize distances
|
||||
for (const node of Object.keys(graph)) {
|
||||
distances[node] = Infinity;
|
||||
}
|
||||
distances[start] = 0;
|
||||
|
||||
const queue = new PriorityQueue({
|
||||
comparator: (a, b) => a.distance - b.distance,
|
||||
});
|
||||
|
||||
queue.queue({ node: start, distance: 0 });
|
||||
|
||||
while (queue.length > 0) {
|
||||
const { node: currentNode, distance: currentDistance } = queue.dequeue();
|
||||
|
||||
if (visited.has(currentNode)) {
|
||||
continue;
|
||||
}
|
||||
visited.add(currentNode);
|
||||
|
||||
if (currentNode === end) {
|
||||
return currentDistance;
|
||||
}
|
||||
|
||||
const neighbors = graph[currentNode] || {};
|
||||
for (const [neighbor, weight] of Object.entries(neighbors)) {
|
||||
if (weight < 0) {
|
||||
throw new Error('Dijkstra\'s algorithm requires non-negative edge weights.');
|
||||
}
|
||||
const newDistance = currentDistance + weight;
|
||||
if (newDistance < distances[neighbor]) {
|
||||
distances[neighbor] = newDistance;
|
||||
queue.queue({ node: neighbor, distance: newDistance });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Infinity;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Finds the total weight of the shortest path between two nodes in a weighted, undirected graph.
|
||||
* Uses Dijkstra's algorithm with a priority queue loaded dynamically from a CDN.
|
||||
*
|
||||
* @param {Object<string, Object<string, number>>} graph - Adjacency list representing the graph.
|
||||
* @param {string} start - Starting node id.
|
||||
* @param {string} end - Target node id.
|
||||
* @returns {Promise<number>} - Total weight of the shortest path, or Infinity if no path exists.
|
||||
*/
|
||||
const findShortestPath = async (graph, start, end) => {
|
||||
// Dynamically import the priority queue implementation from jsDelivr
|
||||
const { default: PriorityQueue } = await import(
|
||||
'https://cdn.jsdelivr.net/npm/js-priority-queue@1.0.0?module'
|
||||
);
|
||||
|
||||
if (!graph || !graph.hasOwnProperty(start) || !graph.hasOwnProperty(end)) {
|
||||
return Infinity;
|
||||
}
|
||||
if (start === end) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const distances = {};
|
||||
const visited = new Set();
|
||||
|
||||
for (const node of Object.keys(graph)) {
|
||||
distances[node] = Infinity;
|
||||
}
|
||||
distances[start] = 0;
|
||||
|
||||
const pq = new PriorityQueue({
|
||||
comparator: (a, b) => a.distance - b.distance,
|
||||
});
|
||||
|
||||
pq.queue({ node: start, distance: 0 });
|
||||
|
||||
while (pq.length > 0) {
|
||||
const { node, distance } = pq.dequeue();
|
||||
|
||||
if (visited.has(node)) continue;
|
||||
visited.add(node);
|
||||
|
||||
if (node === end) {
|
||||
return distance;
|
||||
}
|
||||
|
||||
for (const [neighbor, weight] of Object.entries(graph[node] || {})) {
|
||||
if (visited.has(neighbor)) continue;
|
||||
|
||||
const newDist = distance + weight;
|
||||
if (newDist < distances[neighbor]) {
|
||||
distances[neighbor] = newDist;
|
||||
pq.queue({ node: neighbor, distance: newDist });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Infinity;
|
||||
};
|
||||
|
||||
// Example usage:
|
||||
// (async () => {
|
||||
// const graph = {
|
||||
// A: { B: 1, C: 4 },
|
||||
// B: { A: 1, C: 2, D: 5 },
|
||||
// C: { A: 4, B: 2, D: 1 },
|
||||
// D: { B: 5, C: 1 }
|
||||
// };
|
||||
// console.log(await findShortestPath(graph, 'A', 'D')); // Output: 4
|
||||
// })();
|
||||
@@ -0,0 +1 @@
|
||||
async function findShortestPath(graph,start,end){const {default:PriorityQueue}=await import('https://cdn.jsdelivr.net/npm/js-priority-queue@latest/+esm');const distances=new Map(Object.keys(graph).map(node=>[node,Infinity]));distances.set(start,0);const visited=new Set();const pq=new PriorityQueue({comparator:(a,b)=>a[0]-b[0]});pq.queue([0,start]);while(pq.length){const [currentDistance,node]=pq.dequeue();if(visited.has(node))continue;if(node===end)return currentDistance;visited.add(node);for(const [neighbor,weight] of Object.entries(graph[node]||{})){const newDistance=currentDistance+weight;if(newDistance<(distances.get(neighbor)??Infinity)){distances.set(neighbor,newDistance);pq.queue([newDistance,neighbor]);}}}return Infinity;}
|
||||
Reference in New Issue
Block a user