Data update
This commit is contained in:
parent
4d5544505c
commit
4924dd0264
3073 changed files with 55820 additions and 4408 deletions
179
Task/Dijkstras-algorithm/Dart/dijkstras-algorithm.dart
Normal file
179
Task/Dijkstras-algorithm/Dart/dijkstras-algorithm.dart
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
import 'dart:math';
|
||||
import 'dart:collection';
|
||||
|
||||
class Edge<T extends num, U> {
|
||||
final U from;
|
||||
final U to;
|
||||
final T weight;
|
||||
|
||||
Edge(this.from, this.to, this.weight);
|
||||
|
||||
@override
|
||||
String toString() => '($from, $to, $weight)';
|
||||
}
|
||||
|
||||
class Digraph<T extends num, U> {
|
||||
final Map<MapEntry<U, U>, T> edges;
|
||||
final Set<U> verts;
|
||||
|
||||
Digraph(this.edges, this.verts);
|
||||
|
||||
factory Digraph.fromEdges(List<Edge<T, U>> edgeList) {
|
||||
final Set<U> vnames = <U>{};
|
||||
final Map<MapEntry<U, U>, T> adjmat = <MapEntry<U, U>, T>{};
|
||||
|
||||
for (final edge in edgeList) {
|
||||
vnames.add(edge.from);
|
||||
vnames.add(edge.to);
|
||||
adjmat[MapEntry(edge.from, edge.to)] = edge.weight;
|
||||
}
|
||||
|
||||
return Digraph(adjmat, vnames);
|
||||
}
|
||||
|
||||
Set<U> get vertices => verts;
|
||||
Map<MapEntry<U, U>, T> get edgeMap => edges;
|
||||
|
||||
Set<MapEntry<U, T>> neighbours(U vertex) {
|
||||
final Set<MapEntry<U, T>> result = <MapEntry<U, T>>{};
|
||||
for (final entry in edges.entries) {
|
||||
if (entry.key.key == vertex) {
|
||||
result.add(MapEntry(entry.key.value, entry.value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class DijkstraResult<T extends num, U> {
|
||||
final List<U> path;
|
||||
final T cost;
|
||||
|
||||
DijkstraResult(this.path, this.cost);
|
||||
}
|
||||
|
||||
DijkstraResult<T, U> dijkstraPath<T extends num, U>(
|
||||
Digraph<T, U> graph, U source, U destination) {
|
||||
|
||||
// Verify source is in graph
|
||||
if (!graph.vertices.contains(source)) {
|
||||
throw ArgumentError('$source is not a vertex in the graph');
|
||||
}
|
||||
|
||||
// Easy case - same source and destination
|
||||
if (source == destination) {
|
||||
return DijkstraResult([source], 0 as T);
|
||||
}
|
||||
|
||||
// Initialize variables
|
||||
final T infinity = (T == int) ?
|
||||
(double.maxFinite.toInt() as T) :
|
||||
(double.maxFinite as T);
|
||||
|
||||
final Map<U, T> dist = <U, T>{};
|
||||
final Map<U, U> prev = <U, U>{};
|
||||
final Set<U> unvisited = Set<U>.from(graph.vertices);
|
||||
final Map<U, Set<MapEntry<U, T>>> neighMap = <U, Set<MapEntry<U, T>>>{};
|
||||
|
||||
// Initialize distances and previous vertices
|
||||
for (final vertex in graph.vertices) {
|
||||
dist[vertex] = infinity;
|
||||
prev[vertex] = vertex;
|
||||
neighMap[vertex] = graph.neighbours(vertex);
|
||||
}
|
||||
dist[source] = 0 as T;
|
||||
|
||||
// Main loop
|
||||
while (unvisited.isNotEmpty) {
|
||||
// Find vertex with minimum distance
|
||||
U? current;
|
||||
T minDist = infinity;
|
||||
for (final vertex in unvisited) {
|
||||
if (dist[vertex]! < minDist) {
|
||||
minDist = dist[vertex]!;
|
||||
current = vertex;
|
||||
}
|
||||
}
|
||||
|
||||
if (current == null || dist[current] == infinity || current == destination) {
|
||||
break;
|
||||
}
|
||||
|
||||
unvisited.remove(current);
|
||||
|
||||
// Update distances to neighbours
|
||||
for (final neighbour in neighMap[current]!) {
|
||||
final U neighbourVertex = neighbour.key;
|
||||
final T edgeCost = neighbour.value;
|
||||
final T alt = (dist[current]! + edgeCost) as T;
|
||||
|
||||
if (alt < dist[neighbourVertex]!) {
|
||||
dist[neighbourVertex] = alt;
|
||||
prev[neighbourVertex] = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reconstruct path
|
||||
final List<U> path = <U>[];
|
||||
final T cost = dist[destination]!;
|
||||
|
||||
if (prev[destination] == destination) {
|
||||
// No path found
|
||||
return DijkstraResult(path, cost);
|
||||
} else {
|
||||
// Build path backwards
|
||||
U current = destination;
|
||||
while (current != source) {
|
||||
path.insert(0, current);
|
||||
current = prev[current]!;
|
||||
}
|
||||
path.insert(0, current);
|
||||
return DijkstraResult(path, cost);
|
||||
}
|
||||
}
|
||||
|
||||
// Test data
|
||||
final List<Edge<int, String>> testGraph = [
|
||||
Edge("a", "b", 7),
|
||||
Edge("a", "c", 9),
|
||||
Edge("a", "f", 14),
|
||||
Edge("b", "c", 10),
|
||||
Edge("b", "d", 15),
|
||||
Edge("c", "d", 11),
|
||||
Edge("c", "f", 2),
|
||||
Edge("d", "e", 6),
|
||||
Edge("e", "f", 9),
|
||||
];
|
||||
|
||||
void testPaths() {
|
||||
final graph = Digraph.fromEdges(testGraph);
|
||||
final String src = "a";
|
||||
final String dst = "e";
|
||||
|
||||
final result = dijkstraPath(graph, src, dst);
|
||||
final String pathStr = result.path.isEmpty
|
||||
? "no possible path"
|
||||
: result.path.join(" → ");
|
||||
|
||||
print("Shortest path from $src to $dst: $pathStr (cost ${result.cost})");
|
||||
|
||||
// Print all possible paths
|
||||
print("\n src | dst | path");
|
||||
print("----------------");
|
||||
|
||||
for (final source in graph.vertices) {
|
||||
for (final dest in graph.vertices) {
|
||||
final pathResult = dijkstraPath(graph, source, dest);
|
||||
final String pathDisplay = pathResult.path.isEmpty
|
||||
? "no possible path"
|
||||
: "${pathResult.path.join(" → ")} (${pathResult.cost})";
|
||||
|
||||
print("${source.toString().padLeft(4)} | ${dest.toString().padLeft(3)} | $pathDisplay");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
testPaths();
|
||||
}
|
||||
165
Task/Dijkstras-algorithm/R/dijkstras-algorithm.r
Normal file
165
Task/Dijkstras-algorithm/R/dijkstras-algorithm.r
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
# Digraph class implementation using S3
|
||||
create_digraph <- function(edges) {
|
||||
# Extract vertex names from edges
|
||||
vnames <- unique(c(edges[, 1], edges[, 2]))
|
||||
|
||||
# Create adjacency list as named list
|
||||
adjmat <- list()
|
||||
for (i in 1:nrow(edges)) {
|
||||
key <- paste(edges[i, 1], edges[i, 2], sep = "->")
|
||||
adjmat[[key]] <- as.numeric(edges[i, 3])
|
||||
}
|
||||
|
||||
# Create digraph object
|
||||
digraph <- list(
|
||||
edges = adjmat,
|
||||
verts = vnames
|
||||
)
|
||||
class(digraph) <- "Digraph"
|
||||
return(digraph)
|
||||
}
|
||||
|
||||
# Accessor functions
|
||||
vertices <- function(g) {
|
||||
return(g$verts)
|
||||
}
|
||||
|
||||
edges <- function(g) {
|
||||
return(g$edges)
|
||||
}
|
||||
|
||||
# Get neighbours of a vertex
|
||||
neighbours <- function(g, v) {
|
||||
neigh <- list()
|
||||
edge_names <- names(g$edges)
|
||||
|
||||
for (edge_name in edge_names) {
|
||||
parts <- strsplit(edge_name, "->")[[1]]
|
||||
if (parts[1] == v) {
|
||||
neigh[[parts[2]]] <- g$edges[[edge_name]]
|
||||
}
|
||||
}
|
||||
return(neigh)
|
||||
}
|
||||
|
||||
# Dijkstra's shortest path algorithm
|
||||
dijkstra_path <- function(g, source, dest) {
|
||||
# Check if source is in graph
|
||||
if (!(source %in% vertices(g))) {
|
||||
stop(paste(source, "is not a vertex in the graph"))
|
||||
}
|
||||
|
||||
# Easy case
|
||||
if (source == dest) {
|
||||
return(list(path = c(source), cost = 0))
|
||||
}
|
||||
|
||||
# Initialize variables
|
||||
inf <- Inf
|
||||
verts <- vertices(g)
|
||||
dist <- setNames(rep(inf, length(verts)), verts)
|
||||
prev <- setNames(verts, verts)
|
||||
dist[source] <- 0
|
||||
Q <- verts
|
||||
|
||||
# Precompute neighbours for all vertices
|
||||
neigh <- list()
|
||||
for (v in verts) {
|
||||
neigh[[v]] <- neighbours(g, v)
|
||||
}
|
||||
|
||||
# Main loop
|
||||
while (length(Q) > 0) {
|
||||
# Find vertex with minimum distance
|
||||
u <- Q[which.min(dist[Q])]
|
||||
Q <- Q[Q != u]
|
||||
|
||||
if (dist[u] == inf || u == dest) break
|
||||
|
||||
# Update distances to neighbours
|
||||
for (v_name in names(neigh[[u]])) {
|
||||
if (v_name %in% Q) {
|
||||
alt <- dist[u] + neigh[[u]][[v_name]]
|
||||
if (alt < dist[v_name]) {
|
||||
dist[v_name] <- alt
|
||||
prev[v_name] <- u
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Reconstruct path
|
||||
path <- c()
|
||||
cost <- dist[dest]
|
||||
|
||||
if (prev[dest] == dest) {
|
||||
return(list(path = path, cost = cost))
|
||||
} else {
|
||||
current <- dest
|
||||
while (current != source) {
|
||||
path <- c(current, path)
|
||||
current <- prev[current]
|
||||
}
|
||||
path <- c(current, path)
|
||||
return(list(path = path, cost = cost))
|
||||
}
|
||||
}
|
||||
|
||||
# Test data
|
||||
testgraph <- matrix(c(
|
||||
"a", "b", 7,
|
||||
"a", "c", 9,
|
||||
"a", "f", 14,
|
||||
"b", "c", 10,
|
||||
"b", "d", 15,
|
||||
"c", "d", 11,
|
||||
"c", "f", 2,
|
||||
"d", "e", 6,
|
||||
"e", "f", 9
|
||||
), ncol = 3, byrow = TRUE)
|
||||
|
||||
# Convert weights to numeric
|
||||
testgraph[, 3] <- as.numeric(testgraph[, 3])
|
||||
|
||||
# Test function
|
||||
test_paths <- function() {
|
||||
g <- create_digraph(testgraph)
|
||||
src <- "a"
|
||||
dst <- "e"
|
||||
|
||||
result <- dijkstra_path(g, src, dst)
|
||||
path <- result$path
|
||||
cost <- result$cost
|
||||
|
||||
cat("Shortest path from", src, "to", dst, ": ")
|
||||
if (length(path) == 0) {
|
||||
cat("no possible path")
|
||||
} else {
|
||||
cat(paste(path, collapse = " → "))
|
||||
}
|
||||
cat(" (cost", cost, ")\n")
|
||||
|
||||
# Print all possible paths
|
||||
cat("\n")
|
||||
cat(sprintf("%4s | %3s | %s\n", "src", "dst", "path"))
|
||||
cat("----------------\n")
|
||||
|
||||
for (src in vertices(g)) {
|
||||
for (dst in vertices(g)) {
|
||||
result <- dijkstra_path(g, src, dst)
|
||||
path <- result$path
|
||||
cost <- result$cost
|
||||
|
||||
path_str <- if (length(path) == 0) {
|
||||
"no possible path"
|
||||
} else {
|
||||
paste0(paste(path, collapse = " → "), " (", cost, ")")
|
||||
}
|
||||
|
||||
cat(sprintf("%4s | %3s | %s\n", src, dst, path_str))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Run the test
|
||||
test_paths()
|
||||
Loading…
Add table
Add a link
Reference in a new issue