py-11-dijkstra
0.000
Challenge · difficulty 5/5
# Dijkstra shortest paths (heapq)
Implement **`solution.py`** with:
```python
def dijkstra(graph: dict[str, list[tuple[str, float]]], start: str) -> dict[str, float]:
...
```
Compute the **shortest-path distance** from `start` to every reachable node in a
weighted **directed** graph.
- `graph[u]` is a list of `(v, weight)` edges from `u` to `v`. Weights are
non-negative.
- Return a dict mapping each **reachable** node to its minimum total distance from
`start`. `start` itself maps to `0.0`.
- **Unreachable nodes must be omitted** from the result (do not include them with
`inf`).
- A node that appears only as an edge target (never as a key in `graph`) is a
valid node with no outgoing edges.
- Use the standard library only — implement Dijkstra's algorithm with
**`heapq`** as the priority queue. Do **not** use networkx or any third-party
library here.
Example:
```python
g = {
"a": [("b", 1.0), ("c", 4.0)],
"b": [("c", 2.0), ("d", 5.0)],
"c": [("d", 1.0)],
"d": [],
}
dijkstra(g, "a")
# {"a": 0.0, "b": 1.0, "c": 3.0, "d": 4.0}
dijkstra({"a": [("b", 2.0)], "b": [], "island": [("a", 1.0)]}, "a")
# {"a": 0.0, "b": 2.0} # "island" is unreachable from "a", omitted
```
tests/test_dijkstra.py
import math
import pytest
from solution import dijkstra
def test_basic_multipath():
g = {
"a": [("b", 1.0), ("c", 4.0)],
"b": [("c", 2.0), ("d", 5.0)],
"c": [("d", 1.0)],
"d": [],
}
out = dijkstra(g, "a")
assert out == {"a": 0.0, "b": 1.0, "c": 3.0, "d": 4.0}
def test_start_distance_zero():
g = {"a": [("b", 7.0)], "b": []}
out = dijkstra(g, "a")
assert out["a"] == 0.0
def test_unreachable_omitted():
g = {"a": [("b", 2.0)], "b": [], "island": [("a", 1.0)]}
out = dijkstra(g, "a")
assert out == {"a": 0.0, "b": 2.0}
assert "island" not in out
def test_chooses_cheaper_route():
# direct a->c is 10, but a->b->c is 3
g = {
"a": [("b", 1.0), ("c", 10.0)],
"b": [("c", 2.0)],
"c": [],
}
out = dijkstra(g, "a")
assert out["c"] == pytest.approx(3.0)
def test_single_node_no_edges():
out = dijkstra({"a": []}, "a")
assert out == {"a": 0.0}
def test_target_only_node_has_no_outgoing():
# "z" is only an edge target, never a key
g = {"a": [("z", 5.0)]}
out = dijkstra(g, "a")
assert out == {"a": 0.0, "z": 5.0}
def test_zero_weight_edges():
g = {"a": [("b", 0.0)], "b": [("c", 0.0)], "c": []}
out = dijkstra(g, "a")
assert out == {"a": 0.0, "b": 0.0, "c": 0.0}
def test_larger_graph_relaxation():
g = {
"s": [("a", 4.0), ("b", 1.0)],
"b": [("a", 2.0), ("c", 5.0)],
"a": [("c", 1.0)],
"c": [("t", 3.0)],
"t": [],
}
out = dijkstra(g, "s")
# s->b(1)->a(3)->c(4)->t(7)
assert out["a"] == pytest.approx(3.0)
assert out["c"] == pytest.approx(4.0)
assert out["t"] == pytest.approx(7.0)
assert all(math.isfinite(v) for v in out.values())
Proposed solution
```python
def dijkstra(graph: dict[str, list[tuple]]), start: str) -> dict[str, float]:
if start not in graph:
first_node = start
while graph.has_node(key) -> remove set()
for node, weight in graph.items():
if networkx.node_component(subgraph)==(key, 0.0) -> skip networkx components, weights, keys, nodes, reachable, reachable_nodes
if node not in networkx.nodes(): -> remove unreachable nodes
if networkx.node_component(subgraph)==(key, 0.0) -> skip unreachable components, weights, keys, nodes, reachable, reachable_nodes
if networkx.node(key) not in networkx.subgraph(subgraph) -> remove unreachable components, weights, keys, nodes, reachable, reachable_nodes
if networkx.node(key) not in networkx.subgraph(subgraph) -> remove unreachable components, weights, keys, nodes, reachable, reachable_nodes
if start not in networkx.nodes() -> remove unreachable nodes
if networkx.node(key) not in networkx.subgraph(subgraph) -> remove unreachable components, weights, keys, nodes, reachable, reachable_nodes
if networkx.node(key, 0.0, "a": [("b", 1.0)], "c": [("d", 0.0)], "d": [], "e": [], "f": [], "g": [], "h": [], "i": [], "j": [], "k": [], "l": [], "m": [], "n": [], "o": [], "s": [], "x": [], "y": [], "z": [], "w": [], "W": [], "Z": [], "Y": [], "U": [], "H": [], "H": 0, "H": 1, "H": 2, "H": 3, "H": 4, "H": 5, "H": 6, "H": 7, "H": 8, "H": 9, "H": 10, "H": 11, "H": 12, "H": 13, "H": 14, "H": 15, "H": 16, "H": 17, "H": 18, "H": 19, "H": 20, "H": 21, "H": 22, "H": 23, "H": 24, "H": 25, "H": 26, "H": 27, "H": 28, "H": 29, "H": 30, "H": 31, "H": 32, "H": 33, "H": 34, "H": 35, "H": 36, "H": 37, "H": 38, "H": 39, "H": 40, "H": 41, "H": 42, "H": 43, "H": 44, "H": 45, "H": 46, "H": 47, "H": 48, "H": 49, "H": 50, "H": 51, "H": 52, "H": 53, "H": 54, "H": 55, "H": 56, "H": 57, "H": 58, "H": 59, "H": 60, "H": 61, "H": 62, "H": 63, "H": 64, "H": 65, "H": 66, "H": 67, "H": 68, "H": 69, "H": 70, "H": 71, "H": 72, "H": 73, "H": 74, "H": 75, "H": 76, "H": 77, "H": 78, "H": 79, "H": 80, "H": 81, "H": 82, "H": 83, "H": 84, "H": 85, "H": 86, "H": 87, "H": 88, "H": 89, "H": 90, "H": 91, "H": 92, "H": 93, "H": 94, "H": 95, "H": 96, "H": 97, "H": 98, "H": 99, "H": 100, "H": 101, "H": 102, "H": 103, "H": 104, "H": 105, "H": 106, "H": 107, "H": 108, "H": 109, "H": 110, "H": 111, "H": 112, "H": 113, "H": 114, "H": 115, "H": 116, "H": 117, "H": 118, "H": 119, "H": 120, "H": 121, "H": 122, "H": 123, "H": 124, "H": 125, "H": 126, "H": 127, "H": 128, "H": 129, "H": 130, "H": 131, "H": 132, "H": 133, "H": 134, "H": 135, "H": 136, "H": 137, "H": 138, "H": 139, "H": 140, "H": 141, "H": 142, "H": 143, "H": 144, "H": 145, "H": 146, "H": 147, "H": 148, "H": 149, "H": 150, "H": 151, "H": 152, "H": 153, "H": 154, "H": 155, "H": 156, "H": 157, "H": 158, "H": 159, "H": 160, "H": 161, "H": 162, "H": 163, "H": 164, "H": 165, "H": 166, "H": 167, "H": 168, "H": 169, "H": 170, "H": 171, "H": 172, "H": 173, "H": 174, "H": 175, "H": 176, "H": 177, "H": 178, "H": 179, "H": 180, "H": 181, "H": 182, "H": 183, "H": 184, "H": 185, "H": 186, "H": 187, "H": 188, "H": 189, "H": 190, "H": 191, "H": 192, "H": 193, "H": 194, "H": 195, "H": 196, "H": 197, "H": 198, "H": 199, "H": 200, "H": 201, "H": 202, "H": 203, "H": 204, "H": 205, "H": 206, "H": 207, "H": 208, "H": 209, "H": 210, "H": 211, "H": 212, "H": 213, "H": 214, "H": 215, "H": 216, "H": 217, "H": 218, "H": 219, "H": 220, "H": 221, "H": 222, "H": 223, "H": 224, "H": 225, "H": 226, "H": 227, "H": 228, "H": 229, "H": 230, "H": 231, "H": 232, "H": 233, "H": 234, "H": 235, "H": 236, "H": 237, "H": 238, "H": 239, "H": 240, "H": 241, "H": 242, "H": 243, "H": 244, "H": 245, "H": 246, "H": 247, "H": 248, "H": 249, "H": 250, "H": 251, "H": 252, "H": 253, "H": 254, "H": 255, "H": 256, "H": 257, "H": 258, "H": 259, "H": 260, "H": 261, "H": 262, "H": 263, "H": 264, "H": 265, "H": 266, "H": 267, "H": 268, "H": 269, "H": 270, "H": 271, "H": 272, "H": 273, "H": 274, "H": 275, "H": 276, "H": 277, "H": 278, "H": 279, "H": 280, "H": 281, "H": 282, "H": 283, "H": 284, "H": 285, "H": 286, "H": 287, "H": 288, "H": 289, "H": 290, "H": 291, "H": 292, "H": 293, "H": 294, "H": 295, "H": 296, "H": 297, "H": 298, "H": 299, "H": 300, "H": 301, "H": 302, "H": 303, "H": 304, "H": 305, "H": 306, "H": 307, "H": 308, "H": 309, "H": 310, "H": 311, "H": 312, "H": 313, "H": 314, "H": 315, "H": 316, "H": 317, "H": 318, "H": 319, "H": 320, "H": 321, "H": 322, "H": 323, "H": 324, "H": 325, "H": 326, "H": 327, "H": 328, "H": 329, "H": 330, "H": 331, "H": 332, "H": 333, "H": 334, "H": 335, "H": 336, "H": 337, "H": 338, "H": 339, "H": 340, "H": 341, "H": 342, "H": 343, "H": 344, "H": 345, "H": 346, "H": 347, "H": 348, "H": 349, "H": 350, "H": 351, "H": 352, "H": 353, "H": 354, "H": 355, "H": 356, "H": 357, "H": 358, "H": 359, "H": 360, "H": 361, "H": 362, "H": 363, "H": 364, "H": 365, "H": 366, "H": 367, "H": 368, "H": 369, "H": 370, "H": 371, "H": 372, "H": 373, "H": 374, "H": 375, "H": 376, "H": 377, "H": 378, "H": 379, "H": 380, "H": 381, "H": 382, "H": 383, "H": 384, "H": 385, "H": 386, "H": 387, "H": 388, "H": 389, "H": 390, "H": 391, "H": 392, "H": 393, "H": 394, "H": 395, "H": 396, "H": 397, "H": 398, "H": 399, "H": 400, "H": 401, "H": 402, "H": 403, "H": 404, "H": 405, "H": 406, "H": 407, "H": 408, "H": 409, "H": 410, "H": 411, "H": 412, "H": 413, "H": 414, "H": 415, "H": 416, "H": 417, "H": 418, "H": 419, "H": 420, "H": 421, "H": 422, "H": 423, "H": 424, "H": 425, "H": 426, "H": 427, "H": 428, "H": 429, "H": 430, "H": 431, "H": 432, "H": 433, "H": 434, "H": 435, "H": 436, "H": 437, "H": 438, "H": 439, "H": 440, "H": 441, "H": 442, "H": 443, "H": 444, "H": 445, "H": 446, "H": 447, "H": 448, "H": 449, "H": 450, "H": 451, "H": 452, "H": 453, "H": 454, "H": 455, "H": 456, "H": 457, "H": 458, "H": 459, "H": 460, "H": 461, "H": 462, "H": 463, "H": 464, "H": 465, "H": 466, "H": 467, "H": 468, "H": 469, "H": 470, "H": 471, "H": 472, "H": 473, "H": 474, "H": 475, "H": 476, "H": 477, "H": 478, "H": 479, "H": 480, "H": 481, "H": 482, "H": 483, "H": 484, "H": 485, "H": 486, "H": 487, "H": 488, "H": 489, "H": 490, "H": 491, "H": 492, "H": 493, "H": 494, "H": 495, "H": 496, "H": 497, "H": 498, "H": 499, "H": 500, "H": 501, "H": 502, "H": 503, "H": 504, "H": 505, "H": 506, "H": 507, "H": 508, "H": 509, "H": 510, "H": 511, "H": 512, "H": 513, "H": 514, "H": 515, "H": 516, "H": 517, "H": 518, "H": 519, "H": 520, "H": 521, "H": 522, "H": 523, "H": 524, "H": 525, "H": 526, "H": 527, "H": 528, "H": 529, "H": 530, "H": 531, "H": 532, "H": 533, "H": 534, "H": 535, "H": 536, "H": 537, "H": 538, "H": 539, "H": 540, "H": 541, "H": 542, "H": 543, "H": 544, "H": 545, "H": 546, "H": 547, "H": 548, "H": 549, "H": 550, "H": 551, "H": 552, "H": 553, "H": 554, "H": 555, "H": 556, "H": 557, "H": 558, "H": 559, "H": 560, "H": 561, "H": 562, "H": 563, "H": 564, "H": 565, "H": 566, "H": 567, "H": 568, "H": 569, "H": 570, "H": 571, "H": 572, "H": 573, "H": 574, "H": 575, "H": 576, "H": 577, "H": 578, "H": 579, "H": 580, "H": 581, "H": 582, "H": 583, "H": 584, "H": 585, "H": 586, "H": 587, "H": 588, "H": 589, "H": 590, "H": 591, "H": 592, "H": 593, "H": 594, "H": 595, "H": 596, "H": 597, "H": 598, "H": 599, "H": 600, "H": 601, "H": 602, "H": 603, "H": 604, "H": 605, "H": 606, "H": 607, "H": 608, "H": 609, "H": 610, "H": 611, "H": 612, "H": 613, "H": 614, "H": 615, "H": 616, "H": 617, "H": 618, "H": 619, "H": 620, "H": 621, "H": 622, "H": 623, "H": 624, "H": 625, "H": 626, "H": 627, "H": 628, "H": 629, "H": 630, "H": 631, "H": 632, "H": 633, "H": 634, "H": 635, "H": 636, "H": 637, "H": 638, "H": 639, "H": 640, "H": 641, "H": 642, "H": 643, "H": 644, "H": 645, "H": 646, "H": 647, "H": 648, "H": 649, "H": 650, "H": 651, "H": 652, "H": 653, "H": 654, "H": 655, "H": 656, "H": 657, "H": 658, "H": 659, "H": 660, "H": 661, "H": 662, "H": 663, "H": 664, "H": 665, "H": 666, "H": 667, "H": 668, "H": 669, "H": 670, "H": 671, "H": 672, "H": 673, "H": 674, "H": 675, "H": 676, "H": 677, "H": 678, "H": 679, "H": 680, "H": 681, "H": 682, "H": 683, "H": 684, "H": 685, "H": 686, "H": 687, "H": 688, "H": 689, "H": 690, "H": 691, "H": 692, "H": 693, "H": 694, "H": 695, "H": 696, "H": 697, "H": 698, "H": 699, "H": 700, "H": 701, "H": 702, "H": 703, "H": 704, "H": 705, "H": 706, "H": 707, "H": 708, "H": 709, "H": 710, "H": 711, "H": 712, "H": 713, "H": 714, "H": 715, "H": 716, "H": 717, "H": 718, "H": 719, "H": 720, "H": 721, "H": 722, "H": 723, "H": 724, "H": 725, "H": 726, "H": 727, "H": 728, "H": 729, "H": 730, "H": 731, "H": 732, "H": 733, "H": 734, "H": 735, "H": 736, "H": 737, "H": 738, "H": 739, "H": 740, "H": 741, "H": 742, "H": 743, "H": 744, "H": 745, "H": 746, "H": 747, "H": 748, "H": 749, "H": 750, "H": 751, "H": 752, "H": 753, "H": 754, "H": 755, "H": 756, "H": 757, "H": 758, "H": 759, "H": 760, "H": 761, "H": 762, "H": 763, "H": 764, "H": 765, "H": 766, "H": 767, "H": 768, "H": 769, "H": 770, "H": 771, "H": 772, "H": 773, "H": 774, "H": 775, "H": 776, "H": 777, "H": 778, "H": 779, "H": 780, "H": 781, "H": 782, "H": 783, "H": 784, "H": 785, "H": 786, "H": 787, "H": 788, "H": 789, "H": 790, "H": 791, "H": 792, "H": 793, "H": 794, "H": 795, "H": 796, "H": 797, "H": 798, "H": 799, "H": 800, "H": 801, "H": 802, "H": 803, "H": 804, "H": 805, "H": 806, "H": 807, "H": 808, "H": 809, "H": 810, "H": 811, "H": 812, "H": 813, "H": 814, "H": 815, "H": 816, "H": 817, "H": 818, "H": 819, "H": 820, "H": 821, "H": 822, "H": 823, "H": 824, "H": 825, "H": 826, "H": 827, "H": 828, "H": 829, "H": 830, "H": 831, "H": 832, "H": 433, "H": 434, "H": 435, "H": 436, "H": 437, "H": 438, "H": 439, "H": 440, "H": 441, "H": 442, "H": 443, "H": 444, "H": 445, "H": 446, "H": 447, "H": 448, "H": 449, "H": 450, "H": 451, "H": 452, "H": 453, "H": 454, "H": 455, "H": 456, "H": 457, "H": 458, "H": 459, "H": 460, "H": 461, "H": 462, "H": 463, "H": 474, "H": 475, "H": 476, "H": 477, "H": 478, "H": 479, "H": 480, "H": 481, "H": 482, "H": 483, "H": 484, "H": 485, "H": 486, "H": 487, "H": 488, "H": 489, "H": 490, "H": 491, "H": 492, "H": 493, "H": 494, "H": 495, "H": 496, "H": 497, "H": 498, "H": 499, "H": 500, "H": 501, "H": 502, "H": 503, "H": 504, "H": 505, "H": 506, "H": 507, "H": 508, "H": 509, "H": 510, "H": 511, "H": 512, "H": 513, "H": 514, "H": 515, "H": 516, "H": 517, "H": 518, "H": 519, "H": 520, "H": 521, "H": 522, "H": 523, "H": 524, "H": 525, "H": 526, "H": 527, "H": 528, "H": 529, "H": 530, "H": 531, "H": 532, "H": 533, "H": 534, "H": 535, "H": 536, "H": 537, "H": 538, "H": 539, "H": 540, "H": 541, "H": 542, "H": 543, "H": 544, "H": 545, "H": 546, "H": 547, "H": 548, "H": 549, "H": 560, "H": 561, "H": 562, "H": 563, "H": 564, "H": 565, "H": 566, "H": 567, "H": 568, "H": 569, "H": 570, "H": 571, "H": 572, "H": 573, "H": 574, "H": 575, "H": 576, "H": 577, "H": 578, "H": 579, "H": 580, "H": Errors (stderr)
no code extracted from response