From 1d74c6eec136591e4f8dda6716db2b96d0c8b0f2 Mon Sep 17 00:00:00 2001 From: Farai Mugaviri Date: Fri, 31 Oct 2025 11:19:16 +0200 Subject: [PATCH 1/2] Added Dijkstra's shortest path problem --- searches/dijkstra.py | 85 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 searches/dijkstra.py diff --git a/searches/dijkstra.py b/searches/dijkstra.py new file mode 100644 index 000000000000..a47000648098 --- /dev/null +++ b/searches/dijkstra.py @@ -0,0 +1,85 @@ +"""Dijkstra's shortest path algorithm. + +This module provides a simple Dijkstra implementation that works on a +graph represented as an adjacency mapping: {node: [(neighbor, weight), ...], ...}. + +Functions: +- dijkstra(graph, source) -> (dist, prev) +- shortest_path(prev, target) -> list + +Doctests include a small example graph. +""" +from __future__ import annotations + +import heapq +from typing import Dict, Iterable, List, Tuple, Any + + +def dijkstra(graph: Dict[Any, Iterable[Tuple[Any, float]]], source: Any) -> Tuple[Dict[Any, float], Dict[Any, Any]]: + """Compute shortest path distances from source to all reachable nodes. + + Args: + graph: adjacency mapping where graph[u] yields (v, weight) pairs. + source: start node. + + Returns: + (dist, prev) + - dist: mapping node -> distance (float). Unreachable nodes are absent. + - prev: mapping node -> predecessor on shortest path (or None for source). + + Example: + >>> graph = { + ... 'A': [('B', 1), ('C', 4)], + ... 'B': [('C', 2), ('D', 5)], + ... 'C': [('D', 1)], + ... 'D': [] + ... } + >>> dist, prev = dijkstra(graph, 'A') + >>> dist['D'] + 4 + >>> shortest_path(prev, 'D') + ['A', 'B', 'C', 'D'] + """ + dist: Dict[Any, float] = {} + prev: Dict[Any, Any] = {} + pq: List[Tuple[float, Any]] = [] # (distance, node) + + heapq.heappush(pq, (0.0, source)) + dist[source] = 0.0 + prev[source] = None + + while pq: + d, u = heapq.heappop(pq) + # Skip stale entries + if d != dist.get(u, float('inf')): + continue + for v, w in graph.get(u, []): + nd = d + float(w) + if nd < dist.get(v, float('inf')): + dist[v] = nd + prev[v] = u + heapq.heappush(pq, (nd, v)) + + return dist, prev + + +def shortest_path(prev: Dict[Any, Any], target: Any) -> List[Any]: + """Reconstruct path from source to target using predecessor map. + + If target is not in `prev`, returns an empty list. + """ + if target not in prev: + return [] + path: List[Any] = [] + cur = target + while cur is not None: + path.append(cur) + cur = prev.get(cur) + path.reverse() + return path + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 2757b6358c898777966ea2a08239214da2be29c7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 09:21:01 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/dijkstra.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/searches/dijkstra.py b/searches/dijkstra.py index a47000648098..f4f24cff5724 100644 --- a/searches/dijkstra.py +++ b/searches/dijkstra.py @@ -9,13 +9,16 @@ Doctests include a small example graph. """ + from __future__ import annotations import heapq from typing import Dict, Iterable, List, Tuple, Any -def dijkstra(graph: Dict[Any, Iterable[Tuple[Any, float]]], source: Any) -> Tuple[Dict[Any, float], Dict[Any, Any]]: +def dijkstra( + graph: Dict[Any, Iterable[Tuple[Any, float]]], source: Any +) -> Tuple[Dict[Any, float], Dict[Any, Any]]: """Compute shortest path distances from source to all reachable nodes. Args: @@ -51,11 +54,11 @@ def dijkstra(graph: Dict[Any, Iterable[Tuple[Any, float]]], source: Any) -> Tupl while pq: d, u = heapq.heappop(pq) # Skip stale entries - if d != dist.get(u, float('inf')): + if d != dist.get(u, float("inf")): continue for v, w in graph.get(u, []): nd = d + float(w) - if nd < dist.get(v, float('inf')): + if nd < dist.get(v, float("inf")): dist[v] = nd prev[v] = u heapq.heappush(pq, (nd, v))