Edit: When I first posted this I forgot to mention the mutable aspect of the question.
TL;DR Let's say we have an array of structures. The this array of structures represents a graph. Each node of the graph is one of those structures. Each of those nodes/structures contains a Vector of indices to other nodes, thus forming a graph structure. Now, the question is: How to pass that array to a recursive function that will walk around the graph, passing the array to itself as it recursively calls itself to move through the graph?
After trying to do this with regular references/borrows for a while I concluded it was not going to be possible. I ended up doing it by wrapping the nodes array in an Rc<RefCell. With suitable '.borrow()'s and .clones()
I managed to get something that works:
#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
struct Node {
id: usize,
exits: Vec<usize>,
}
...
fn search (nodes: Rc<RefCell<Nodes>>, start_node: usize, current_node: usize, path: Vec<usize>, depth: usize) -> usize {
// Bail out if recursion depth is crazy
if (depth == 30usize) {
panic!();
}
// Get the current node.
let mut node = nodes.borrow()[current_node].clone();
// Have we returned to the node we started from having made a loop?
if (node.id == start_node) && (path.len() > 2) {
println!("Path: {:?}", path);
return depth;
}
// Have we already been here?
if path.contains(&node.id) {
return depth;
}
// Add the current node to the path.
let mut path = path.clone();
path.push(node.id);
let mut path_length = 0usize;
for (i, connection) in node.exits.iter().enumerate() {
let l = search(nodes.clone(), start_node, *connection, path.clone(), depth + 1);
path_length = std::cmp::max(path_length, l);
}
// Return the longest path found.
path_length
}
...
let mut nodes = Rc::new(RefCell::new(nodes));
let path: Vec<usize> = vec![];
let path_length = search(nodes, 0, 0, path, 0);
println!("Longest path = {}", path_length);
What does anyone think? Any better ways to do this? Other comments?
The longer story is that on another forum some folks were discussing getting some original sources of the famous "Hunt The Wumpus" game to compile. Pre ANSI C and all that. There was also the issue of fixing a bug in one of them that hung up as it tried to generate random mazes of 20 nodes and three exits each.
Which got me curious as to how I would do it in Rust. The code to my Wumpus maze generator, including this recursive walk function is here for the curious: Rust Playground
It generates graphs that look like this: