// Author: CCS // I follow literally code in C, done many years ago fn main() { // Adjacency matrix as a map // Example 01 graph_01 := { 'A': ['B', 'C'] 'B': ['A', 'D', 'E'] 'C': ['A', 'F'] 'D': ['B'] 'E': ['F', 'B', 'F'] 'F': ['C', 'E'] } // Example 02 graph_02 := { 'A': ['B', 'C', 'D'] 'B': ['E'] 'C': ['F'] 'D': ['E'] 'E': ['H'] 'F': ['H'] 'G': ['H'] 'H': ['E', 'F', 'G'] } // println('Graph: $graph') path_01 := depth_first_search_path(graph_01, 'A', 'F') println('\n Graph_01: a first path from node A to node F is: ${path_01.reverse()}') path_02 := depth_first_search_path(graph_02, 'A', 'H') println('\n Graph_02: a first path from node A to node H is: ${path_02.reverse()}') } // Depth-First Search (BFS) allows you to find a path between two nodes in the graph. fn depth_first_search_path(graph map[string][]string, start string, target string) []string { mut path := []string{} // ONE PATH with SUCCESS = array mut stack := []string{} // a stack ... many nodes // all_nodes := graph.keys() // get a key of this map mut visited := visited_init(graph) // a map fully with false in all vertex // false ... not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false} stack << start // first push on the stack for stack.len > 0 { mut node := stack.pop() // get the top node and remove it from the stack // check if this node is already visited if visited[node] == false { // if no ... test it and search for a final node visited[node] = true // means: node visited if node == target { path = build_path_reverse(graph, start, node, visited) return path } // Exploring of node removed from stack and add its relatives print('\n Exploring of node ${node} (true/false): ${graph[node]}') // graph[node].reverse() take a classical choice for DFS // at most os left in this case. // use vertex in graph[node] the choice is right // take all nodes from the node for vertex in graph[node].reverse() { // println("\n ...${vertex}") // not explored yet if visited[vertex] == false { stack << vertex } } print('\n Stack: ${stack} (only not visited) \n Visited: ${visited}') } } path = ['Path not found, problem in the Graph, start or end nodes! '] return path } // Creating aa map to initialize with of visited nodes .... all with false in the init // so these nodes are NOT VISITED YET fn visited_init(a_graph map[string][]string) map[string]bool { mut temp := map[string]bool{} // attention in these initializations with maps for i, _ in a_graph { temp[i] = false } return temp } // Based in the current node that is final, search for his parent, that is already visited, up to the root or start node fn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string { print('\n\n Nodes visited (true) or no (false): ${visited}') array_of_nodes := graph.keys() mut current := final mut path := []string{} path << current for current != start { for i in array_of_nodes { if current in graph[i] && visited[i] == true { current = i break // the first occurrence is enough } } path << current // updating the path tracked } return path } //*****************************************************