예제 #1
0
def find_ladders(beginWord, endWord, wordList):
    """
    :type beginWord: str
    :type endWord: str
    :type wordList: List[str]
    :rtype: List[List[str]]
    """
    # ensure we add the beginWord to the graph
    graph_words = [beginWord] + wordList
    graph = Graph.from_same_length_word_list(graph_words)

    # to trace our path back when we find the target
    parent_of = defaultdict(lambda: [])
    depth = defaultdict(lambda: math.inf)
    depth[beginWord] = 0
    queue = Queue()
    queue.enqueue(beginWord)

    success = False
    while (not queue.is_empty()):
        current = queue.dequeue()
        if (current == endWord):
            success = True

        for child in graph.get_neighbors(current):
            not_encountered_yet = depth[child] == math.inf
            already_encountered_at_same_depth = depth[
                child] == depth[current] + 1

            if (not_encountered_yet):
                depth[child] = depth[current] + 1
                parent_of[child].append(current)
                queue.enqueue(child)
            elif (already_encountered_at_same_depth):
                parent_of[child].append(current)

    if success:
        all_paths = DoublyLinkedList()
        current_path = DoublyLinkedList()
        dfs(parent_of, endWord, all_paths, current_path)
        return all_paths.to_array_from_head()
    else:
        return []
 def setup_method(self):
     self.graph = Graph()
     self.TestClass = None
class DepthFirstPathsTestCommon:
    def setup_method(self):
        self.graph = Graph()
        self.TestClass = None

    def build_default_graph(self):
        self.graph.add_edge(0, 1)
        self.graph.add_edge(0, 2)
        self.graph.add_edge(0, 5)
        self.graph.add_edge(1, 2)
        self.graph.add_edge(2, 3)
        self.graph.add_edge(2, 4)
        self.graph.add_edge(3, 4)
        self.graph.add_edge(3, 5)

        self.graph.add_edge(6, 7)
        self.graph.add_edge(6, 8)
        self.graph.add_edge(7, 8)

    def assert_has_path_to(self, paths, keys):
        for key in keys:
            assert paths.has_path_to(self.graph.vertex(key))

    def assert_not_has_path_to(self, paths, keys):
        for key in keys:
            assert not paths.has_path_to(self.graph.vertex(key))

    def assert_path(self, paths, to_vertex_key, expected_keys):
        vertices = paths.path_to(self.graph.vertex(to_vertex_key))
        keys = [v.key for v in vertices]
        assert has_same_items(keys, expected_keys)

    def test_check_has_path(self):
        self.build_default_graph()

        paths = self.TestClass(self.graph, self.graph.vertex(0))
        self.assert_has_path_to(paths, [0, 1, 2, 3, 4, 5])
        self.assert_not_has_path_to(paths, [6, 7, 8])

        paths = self.TestClass(self.graph, self.graph.vertex(7))
        self.assert_has_path_to(paths, [6, 7, 8])
        self.assert_not_has_path_to(paths, [0, 1, 2, 3, 4, 5])

    def test_get_paths(self):
        self.build_default_graph()

        paths = self.TestClass(self.graph, self.graph.vertex(0))

        self.assert_path(paths, 0, [0])
        self.assert_path(paths, 1, [0, 1])
        self.assert_path(paths, 2, [0, 1, 2])
        self.assert_path(paths, 3, [0, 1, 2, 3])
        self.assert_path(paths, 4, [0, 1, 2, 3, 4])
        self.assert_path(paths, 5, [0, 1, 2, 3, 5])

        self.assert_path(paths, 6, [])
        self.assert_path(paths, 7, [])
        self.assert_path(paths, 8, [])
 def setup_method(self):
     self.graph = Graph()
class TestConnectedComponents:

    def setup_method(self):
        self.graph = Graph()

    def build_default_graph(self):
        self.graph.add_edge(0, 1)
        self.graph.add_edge(0, 2)
        self.graph.add_edge(0, 5)
        self.graph.add_edge(1, 2)
        self.graph.add_edge(2, 3)
        self.graph.add_edge(2, 4)
        self.graph.add_edge(3, 4)
        self.graph.add_edge(3, 5)

        self.graph.add_edge(6, 7)
        self.graph.add_edge(6, 8)
        self.graph.add_edge(7, 8)

    def test_find_connected_components(self):
        self.build_default_graph()
        cc = ConnectedComponents(self.graph)

        assert cc.count() == 2

        self.assert_connected(cc, [0, 1, 2, 3, 4, 5])
        self.assert_connected(cc, [6, 7, 8])

        self.assert_not_connected(cc, 0, [6, 7, 8])
        self.assert_not_connected(cc, 7, [0, 1, 2, 3, 4, 5])

    def assert_connected(self, cc, connected_vertices_keys):
        for i in range(len(connected_vertices_keys) - 1):
            for j in range(i + 1, len(connected_vertices_keys)):
                v1 = self.graph.vertex(connected_vertices_keys[i])
                v2 = self.graph.vertex(connected_vertices_keys[j])
                assert cc.connected(v1, v2)
                assert cc.component_id(v1) == cc.component_id(v2)

    def assert_not_connected(self, cc, key, unconnected_vertices_keys):
        v = self.graph.vertex(key)
        for key in unconnected_vertices_keys:
            other_v = self.graph.vertex(key)
            assert not cc.connected(v, other_v)
            assert cc.component_id(v) != cc.component_id(other_v)
예제 #6
0
class TestGraph:
    def setup_method(self):
        self.graph = Graph()

    def test_add_vertex(self):
        self.graph.add_vertex(1)
        assert self.graph.vertex(1).key == 1

    def test_add_vertex_update_existing(self):
        self.graph.add_vertex(1, 100)
        assert self.graph.vertex(1).value == 100

        self.graph.add_vertex(1, 200)
        assert self.graph.vertex(1).value == 200

    def test_add_edge_should_add_vertex_if_not_exist(self):
        assert self.graph.vertex(1) is None
        assert self.graph.vertex(2) is None

        self.graph.add_edge(1, 2)

        assert self.graph.vertex(1) is not None
        assert self.graph.vertex(2) is not None

    def test_get_adjacents(self):
        self.graph.add_vertex(1)
        self.graph.add_edge(1, 2)
        self.graph.add_edge(1, 3)

        self.assert_adjacents(1, [2, 3])
        self.assert_adjacents(2, [1])
        self.assert_adjacents(3, [1])

    def assert_adjacents(self, key, expected_adj_keys):
        adjacents = self.graph.adj(key)
        adj_keys = [adj.key for adj in adjacents]
        assert has_same_items(adj_keys, expected_adj_keys)
class TestDepthFirstSearch:
    def setup_method(self):
        self.graph = Graph()

    def test_search_all_connected_vertices(self):
        self.graph.add_edge(0, 1)
        self.graph.add_edge(0, 2)
        self.graph.add_edge(0, 5)
        self.graph.add_edge(1, 2)
        self.graph.add_edge(2, 3)
        self.graph.add_edge(2, 4)
        self.graph.add_edge(3, 4)
        self.graph.add_edge(3, 5)

        self.graph.add_edge(6, 7)
        self.graph.add_edge(6, 8)
        self.graph.add_edge(7, 8)

        dfs = DepthFirstSearch(self.graph.vertex(0))
        assert dfs.count() == 6
        self.assert_marked(dfs, [0, 1, 2, 3, 4, 5])

        dfs = DepthFirstSearch(self.graph.vertex(6))
        assert dfs.count() == 3
        self.assert_marked(dfs, [6, 7, 8])

    def assert_marked(self, dfs, marked_keys):
        for key in marked_keys:
            assert dfs.marked(self.graph.vertex(key))