43 lines
954 B
Python
43 lines
954 B
Python
from collections import deque
|
|
from collections.abc import Callable, Hashable, Iterable
|
|
|
|
|
|
def find_chain[T: Hashable](
|
|
objects: Iterable[T],
|
|
start: T,
|
|
end: T,
|
|
is_next: Callable[[T, T], bool]
|
|
) -> list[T]:
|
|
nodes = list(objects)
|
|
|
|
if start == end:
|
|
return [start]
|
|
|
|
visited: set[T] = {start}
|
|
parent: dict[T, T | None] = {start: None}
|
|
queue = deque([start])
|
|
|
|
while queue:
|
|
current = queue.popleft()
|
|
|
|
for node in nodes:
|
|
if node not in visited and is_next(current, node):
|
|
visited.add(node)
|
|
parent[node] = current
|
|
queue.append(node)
|
|
|
|
if node == end:
|
|
queue.clear()
|
|
break
|
|
|
|
if end not in parent:
|
|
return []
|
|
|
|
path: list[T] = []
|
|
curr: T | None = end
|
|
while curr is not None:
|
|
path.append(curr)
|
|
curr = parent[curr]
|
|
|
|
return path[::-1]
|