2022-06-02 07:11:29 +03:00
|
|
|
// Author: CCS
|
2022-04-22 12:01:29 +03:00
|
|
|
// 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')
|
2022-11-15 16:53:13 +03:00
|
|
|
println('\n Graph_01: a first path from node A to node F is: ${path_01.reverse()}')
|
2022-04-22 12:01:29 +03:00
|
|
|
path_02 := depth_first_search_path(graph_02, 'A', 'H')
|
2023-01-25 22:58:44 +03:00
|
|
|
println('\n Graph_02: a first path from node A to node H is: ${path_02.reverse()}')
|
2022-04-22 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2022-06-02 07:11:29 +03:00
|
|
|
mut visited := visited_init(graph) // a map fully with false in all vertex
|
2022-04-22 12:01:29 +03:00
|
|
|
// 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 searchin 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
|
2022-11-15 16:53:13 +03:00
|
|
|
print('\n Exploring of node ${node} (true/false): ${graph[node]}')
|
2022-04-22 12:01:29 +03:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
2022-11-15 16:53:13 +03:00
|
|
|
print('\n Stack: ${stack} (only not visited) \n Visited: ${visited}')
|
2022-04-22 12:01:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
path = ['Path not found, problem in the Graph, start or end nodes! ']
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
|
2022-06-02 07:11:29 +03:00
|
|
|
// 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
|
2023-01-25 22:58:44 +03:00
|
|
|
for i, _ in a_graph {
|
2022-06-02 07:11:29 +03:00
|
|
|
temp[i] = false
|
2022-04-22 12:01:29 +03:00
|
|
|
}
|
2022-06-02 07:11:29 +03:00
|
|
|
return temp
|
2022-04-22 12:01:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2022-11-15 16:53:13 +03:00
|
|
|
print('\n\n Nodes visited (true) or no (false): ${visited}')
|
2022-04-22 12:01:29 +03:00
|
|
|
array_of_nodes := graph.keys()
|
|
|
|
mut current := final
|
|
|
|
mut path := []string{}
|
|
|
|
path << current
|
|
|
|
|
|
|
|
for current != start {
|
|
|
|
for i in array_of_nodes {
|
2023-04-04 13:47:48 +03:00
|
|
|
if current in graph[i] && visited[i] == true {
|
2022-04-22 12:01:29 +03:00
|
|
|
current = i
|
|
|
|
break // the first ocurrence is enough
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path << current // updating the path tracked
|
|
|
|
}
|
|
|
|
return path
|
|
|
|
}
|
2022-06-02 07:11:29 +03:00
|
|
|
|
|
|
|
//*****************************************************
|